Analysis for the research project: This contains:
- The downstream analysis of all the datasets(filtering of patients,
pre-processing, differential expression, pathway enrichment) (starts at
line 89)
- The patient demographic information(starts at line 1472)
- The data manipulation of the differential expression analysis
results (starts at line 1647)
- The calculation of mean drug sensitivity scores of specified
features (starts at line 1801).
load all required packages:
# Install necessary packages for the project
if (!requireNamespace("BiocManager", quietly = TRUE))
install.packages("BiocManager")
install.packages(c("readxl", "dplyr", "limma", "ggplot2"))
BiocManager::install(c("DESeq2", "clusterProfiler", "org.Hs.eg.db", "limma", "DOSE"))
BiocManager::install("preprocessCore")
install.packages("ggrepel")
install.packages("xfun")
#libraries
library(readxl)
library(dplyr)
library(limma)
library(DESeq2)
library(clusterProfiler)
library(org.Hs.eg.db)
library(limma)
library(DOSE)
library(ggplot2)
library(ggrepel)
library(preprocessCore)
install.packages("knitr")
install.packages("rmarkdown")
library(rmarkdown)
library(knitr)
# Install gprofiler2
if (!requireNamespace("gprofiler2", quietly = TRUE)) {
install.packages("gprofiler2")
}
library(gprofiler2)
#datasets used
prot_quant_data <- read.csv("prot_quant_poorrisk_aml.csv")
rna_data <- read.csv("RNAseq both BCI and FINN.csv")
ksea_data <- read.csv("KSEA poor risk AML dist all.csv")
phosphoprotein_data <- read.csv("phosphoproteins_sum_ppsites_poor_risk_aml.csv")
ppindex_data <- read.csv("ppindex_poorrisk_aml.csv")
Table_of_sDSS <- read_excel("Table_of_sDSS.xlsx")
#in data frames
phosphoprotein_data <- data.frame(phosphoprotein_data) # 88
ppindex_data <- data.frame(ppindex_data) # 85
prot_quant_data <- data.frame(prot_quant_data) # 92
rna_data <- data.frame(rna_data) # 77
ksea_data <- data.frame(ksea_data) # 85
#patient info
patients_list <- read_excel("patient_list.xlsx", sheet = "Sheet1")
patients_list <- data.frame(patients_list)
pt_info <- read_excel("Poor risk AML clinical and genomic data.xltx")
Clarify patients:
# Classify patients into the top 20 of the two extremes, top 20 with shortest survival (less than 0.436 years) and top 20 of the longest survival (higher than 1.854 years)
short_survivals <- patients_list %>%
filter(`SURVIVAL..YRS.` < 0.436) %>%
arrange(`SURVIVAL..YRS.`) %>%
head(20)
long_survivals <- patients_list %>%
filter(`SURVIVAL..YRS.` > 1.854) %>%
arrange(desc(`SURVIVAL..YRS.`)) %>%
head(20)
# Extract the sample names
short_samples <- short_survivals$Sample_Name
long_samples <- long_survivals$Sample_Name
PHOSPHOPROTEINS
# Filter the phosphoprotein data
phosphoproteins_filtered <- phosphoprotein_data %>%
dplyr::select(phosphoprotein, n.phosphopeptides, sites, all_of(short_samples), all_of(long_samples))
dim(phosphoproteins_filtered)
[1] 5885 43
Pre-processing steps:
# Boxplot before preprocessing
boxplot(phosphoproteins_filtered[, -c(1:3)], las = 3, main = "Phosphoprotein Data Distribution Before Preprocessing", cex.main = 2) # to increase title text size

#filtering low counts
keep_phospho <- rowSums(phosphoproteins_filtered[, -c(1:3)] >= 10) >= 3
phosphoproteins_filtered <- phosphoproteins_filtered[keep_phospho,]
# Log2 transformation
log2_transformed <- phosphoproteins_filtered
log2_transformed[, -c(1:3)] <- log2(phosphoproteins_filtered[, -c(1:3)] + 1)
# Quantile normalization
quantile_normalized <- log2_transformed
quantile_normalized[, -c(1:3)] <- normalize.quantiles(as.matrix(log2_transformed[, -c(1:3)]))
# Scaling (centering and scaling)
scaled <- quantile_normalized
scaled[, -c(1:3)] <- scale(quantile_normalized[, -c(1:3)], center = TRUE, scale = TRUE)
# Create the final preprocessed dataset
phospho_final <- scaled
# Boxplot after preprocessing
boxplot(phospho_final[, -c(1:3)], las = 3, main = "Phosphoprotein Data Distribution After Preprocessing (Log2, Quantile Normalization, Scaling)", cex.main = 2)

NA
NA
Differential expression analysis using limma: use compare.by.limma
function - the same used in all:
compare.by.limma <- function(df.to.compare, control.samples, test.samples){
# Load library
library(limma)
# Define the columns for control and test samples
control.samples <- intersect(control.samples, colnames(df.to.compare))
test.samples <- intersect(test.samples, colnames(df.to.compare))
# Subset the dataframe to include only the control and test samples
df.s <- df.to.compare[, c(control.samples, test.samples)]
# Create outcome labels for the samples
df.s1 <- data.frame(outcome = rep("control", length(control.samples)))
df.s2 <- data.frame(outcome = rep("test", length(test.samples)))
df.ss <- rbind(df.s1, df.s2)
# Create the design matrix for limma
des <- factor(ifelse(df.ss$outcome == "test", "1", "2"))
facna <- addNA(des)
design <- model.matrix(~ 0 + factor(c(facna)))
colnames(design) <- c("control", "test")
# Define the contrast matrix
contrast.matrix <- makeContrasts(test - control, levels = design)
# Fit the linear model
fit <- lmFit(df.s, design)
fit2 <- contrasts.fit(fit, contrast.matrix)
fit2 <- eBayes(fit2)
# Extract p-values and coefficients
pvals <- data.frame(fit2$p.value)
fvals <- data.frame(fit2$coefficients)
# Create the result dataframe with dynamic column names
df.xx <- data.frame(protein = df.to.compare[,1],
difference_test_vs_control = fvals,
pvalues = pvals)
colnames(df.xx) <- c( "X", "difference.long.vs.short", "pvalues") #the first column is named X, because of the different datasets and different names, needed a common name for analysis
# Adjust p-values - FDR
df.xx$FDR <- p.adjust(df.xx$pvalues, method = "fdr")
return(df.xx)
}
#note: the positive:most expressed in the short survival
# Perform differential expression analysis
df.limma.phospho <- compare.by.limma(phospho_final, long_samples, short_samples)
# Define the p-value threshold for significance
p_value_threshold <- 0.05
# Filter significant results based on the p-value
significant_phospho_results <- df.limma.phospho[df.limma.phospho$pvalues < p_value_threshold, ]
# View all significant results
print(significant_phospho_results)
# Order the significant results by absolute differential expression / most expressed but also p-value <0.05
significant_ph_res <- significant_phospho_results[order(abs(significant_phospho_results$difference.long.vs.short), decreasing = TRUE), ]
# Filter the top 10 most significant hits
top_significant_ph <- head(significant_ph_res, 10)
# View the top 10
print(top_significant_ph)
NA
NA
NA

Pathway enrichment analysis:
GO Enrichment
# Load necessary libraries
library(clusterProfiler)
library(org.Hs.eg.db)
# Extract significant phosphoproteins
significant_ph <- significant_phospho_results$X
# Convert to Entrez IDs
ph_entrez_ids <- bitr(significant_ph, fromType="SYMBOL", toType="ENTREZID", OrgDb=org.Hs.eg.db)
'select()' returned 1:1 mapping between keys and columns
Warning in bitr(significant_ph, fromType = "SYMBOL", toType = "ENTREZID", :
6.67% of input gene IDs are fail to map...
#6.67% of input gene IDs are fail to map...
# Perform GO enrichment analysis
#biological processes
go_ph_enrichment <- enrichGO(gene = ph_entrez_ids$ENTREZID,
OrgDb = org.Hs.eg.db,
ont = "BP", # "BP" for Biological Processes
pAdjustMethod = "none", # Ensures that unadjusted p-values are used
pvalueCutoff = 0.01, #stingest cuttoff value
qvalueCutoff = 0.2,
readable = TRUE)
# other categories (MF, CC)
go_enrichment_ph_MF <- enrichGO(gene = ph_entrez_ids$ENTREZID,
OrgDb = org.Hs.eg.db,
ont = "MF",
pAdjustMethod = "none", #"MF" for Molecular Functions,
pvalueCutoff = 0.01,
qvalueCutoff = 0.2,
readable = TRUE)
go_enrichment_ph_CC <- enrichGO(gene = ph_entrez_ids$ENTREZID,
OrgDb = org.Hs.eg.db,
ont = "CC", #"CC" for Cellular Components
pAdjustMethod = "none",
pvalueCutoff = 0.01,
qvalueCutoff = 0.2,
readable = TRUE)
# Visualize for GO biological processes pathways
barplot(go_ph_enrichment, showCategory = 10, title = "GO Biological Processes Enrichment of Phosphoprotein data")

dotplot(go_ph_enrichment, showCategory = 10, title = "GO Biological Processes Enrichment of Phosphoprotein data")

# Use heatplot
heatplot(go_ph_enrichment, showCategory = 10)

#network plot
cnetplot(go_ph_enrichment, showCategory = 10, title = "Gene-Concept Network for Biological Processes of Phosphoprotein data",
max.overlaps = 100, node_label_size = 3, label_fontsize = 8) +
theme(axis.text.x = element_text(size = 10),
axis.text.y = element_text(size = 10),
plot.title = element_text(size = 14, face = "bold"))

#decided on the number 7 for the categories, as more overwhelms the plot and data points were unlabeled
# Visualize the other categories: MF, CC
#molecular functions
dotplot(go_enrichment_ph_MF, showCategory = 10, title = "GO Molecular Functions Enrichment of Phosphoprotein data")

#cellular componentns
dotplot(go_enrichment_ph_CC, showCategory = 10, title = "GO Cellular Components Enrichment of Phosphoprotein data")

For specifically bad-responders/ targets associated with short
survival:
#subset the data, keep only upregulated features in short survival group
subset_ph <- subset(significant_phospho_results, difference.long.vs.short > 0)
clean_subset_ph <- subset_ph$X
# Convert these kinase names to Entrez IDs
en_ids_ph <- bitr(clean_subset_ph, fromType = "SYMBOL", toType = "ENTREZID", OrgDb = org.Hs.eg.db)
'select()' returned 1:1 mapping between keys and columns
Warning in bitr(clean_subset_ph, fromType = "SYMBOL", toType = "ENTREZID", :
8.57% of input gene IDs are fail to map...
#GO enrichment
go_ph_p_enrichment <- enrichGO(gene = en_ids_ph$ENTREZID,
OrgDb = org.Hs.eg.db,
ont = "BP", # "BP" for Biological Processes
pAdjustMethod = "BH",
pvalueCutoff = 0.05,
qvalueCutoff = 0.2,
readable = TRUE)
#Plots
barplot(go_ph_p_enrichment, showCategory = 10, title = "GO Biological Processes enriched in short survival group")

dotplot(go_ph_p_enrichment, showCategory = 10, title = "GO Biological Processes enriched in short survival group")

heatplot(go_ph_p_enrichment, showCategory = 10)

#network plot
cnetplot(go_ph_p_enrichment, showCategory = 4, title = "Gene-Concept Network for Biological Processes enriched in short survival group",
max.overlaps = 100, node_label_size = 3, label_fontsize = 8) +
theme(axis.text.x = element_text(size = 10),
axis.text.y = element_text(size = 10),
plot.title = element_text(size = 14, face = "bold"))

#decided on 4 to not overwhelm the plot
Using gprofiler2/ for all significant differentially expresssed
features:
# Run gProfiler enrichment analysis
gostres_ph <- gost(query = ph_entrez_ids$ENTREZID,
organism = "hsapiens",
sources = c("GO:BP", "GO:MF", "GO:CC", "KEGG", "REAC", "WP"),
significant = TRUE,
correction_method = "fdr",
user_threshold = 0.05)
# View the results
head(gostres_ph$result)
# Plot the results
gostplot(gostres_ph, capped = TRUE, interactive = FALSE)

#Enhance function to plot results for a specific category (GO, KEGG, REACTOME, WIKIPATHWAYS) + add colors
plot_results <- function(results, category, title) {
filtered_results <- results %>%
filter(source == category) %>%
arrange(p_value) %>%
head(10) # Top 10 results
ggplot(filtered_results, aes(x = reorder(term_name, -p_value), y = -log10(p_value), fill = -log10(p_value))) +
geom_col() +
coord_flip() +
scale_fill_gradient(low = "lightblue", high = "darkblue") + # Gradient color fill
labs(title = title, x = "Pathway", y = "-log10(p-value)") +
theme_minimal() +
theme(
plot.title = element_text(size = 16, face = "bold"),
axis.text.x = element_text(size = 12),
axis.text.y = element_text(size = 12),
legend.position = "none"
)
}
# Plot for each caterogy
bp_plot_ph <- plot_results(gostres_ph$result, "GO:BP", "Top Biological Processes of Phosphoprotein data")
mf_plot_ph <- plot_results(gostres_ph$result, "GO:MF", "Top Molecular Functions of Phosphoprotein data")
cc_plot_ph <- plot_results(gostres_ph$result, "GO:CC", "Top Cellular Components of Phosphoprotein data")
reac_plot_ph <- plot_results(gostres_ph$result, "REAC", "Top Reactome Pathways of Phosphoprotein data")
kegg_plot_ph <- plot_results(gostres_ph$result, "KEGG", "Top KEGG Pathways of Phosphoprotein data")
wp_plot_ph <- plot_results(gostres_ph$result, "WP", "Top WikiPathways of Phosphoprotein data")
# Print the plots
print(bp_plot_ph)

print(mf_plot_ph)

print(cc_plot_ph)

print(reac_plot_ph) #No Reactome pathways identified

print(kegg_plot_ph) #No KEGG pathays identified

print(wp_plot_ph) #NO Wiki Pathways identified

PP_INDEX data:
# Filter ppindex data
ppindex_filtered <- ppindex_data %>%
dplyr::select(X, all_of(short_samples), all_of(long_samples))
dim(ppindex_filtered)
[1] 27599 41
Pre-processing steps:
# Boxplot before preprocessing
boxplot(ppindex_filtered[, -1], las = 3, main = "ppIndex Data Distribution Before Preprocessing", cex.main = 2) # to increase title text size

# Filter out low counts
keep_ppindex <- rowSums(ppindex_filtered[, -1] >= 10) >= 3
ppindex_filtered <- ppindex_filtered[keep_ppindex,]
# Log2 transformation
log2_transformed <- ppindex_filtered
log2_transformed[, -1] <- log2(ppindex_filtered[, -1] + 1)
# Quantile normalization
quantile_normalized <- log2_transformed
quantile_normalized[, -1] <- normalize.quantiles(as.matrix(log2_transformed[, -1]))
# Scaling (centering and scaling)
scaled <- quantile_normalized
scaled[, -1] <- scale(quantile_normalized[, -1], center = TRUE, scale = TRUE)
# final preprocessed dataset
ppindex_final <- scaled
# Boxplot after preprocessing
boxplot(ppindex_final[, -1], las = 3, main = "ppIndex Data Distribution After Preprocessing (Log2, Quantile Normalization, Scaling)", cex.main = 2)

Differential exression analysis - limma:
# Perform differential analysis
df.limma.pp <- compare.by.limma(ppindex_final, long_samples, short_samples)
# Filter significant results based on p-value
significant_pp_results <- df.limma.pp[df.limma.pp$pvalues < p_value_threshold, ]
#print the significant results
print(significant_pp_results)
# Order the significant results by absolute differential expression / most expressed but also pvalue <0.05
significant_pp_res <- significant_pp_results[order(abs(significant_pp_results$difference.long.vs.short), decreasing = TRUE), ]
# View the top 10 most significant hits
top_significant_pp <- head(significant_pp_res, 10)
#print top 10
print(top_significant_pp)
NA
NA
# volcano plot for the differential expression results
ggplot(df.limma.pp, aes(x = difference.long.vs.short, y = -log10(pvalues))) +
geom_point(aes(color = pvalues < pval_threshold)) +
theme_minimal() +
labs(title = "Volcano Plot for PP-index Data",
x = "Log2 Fold Change",
y = "-log10(p-value)") +
geom_text_repel(data = top_significant_pp, #add in text the top 10 results
aes(label = X),
size = 3,
max.overlaps = Inf) + # Use Inf to avoid filtering out top 5
scale_color_manual(values = c("red", "blue"), name = "pvalues < 0.05") +
theme(legend.position = "right")

Pathway enrichment analysis:
GO Enrichment
# Extract the symbols
significant_pp <- unique(sapply(strsplit(significant_pp_results$X, "\\("), `[`, 1))
# Convert to Entrez IDs
entrez_ids_pp <- bitr(significant_pp, fromType = "SYMBOL", toType = "ENTREZID", OrgDb = org.Hs.eg.db)
'select()' returned 1:1 mapping between keys and columns
Warning in bitr(significant_pp, fromType = "SYMBOL", toType = "ENTREZID", :
8.16% of input gene IDs are fail to map...
##8.16% of input gene IDs are fail to map...
# Perform GO enrichment analysis
go_pp_enrichment <- enrichGO(gene = entrez_ids_pp$ENTREZID,
OrgDb = org.Hs.eg.db,
ont = "BP", # "BP" for Biological Processes
pAdjustMethod = "BH",
pvalueCutoff = 0.05,
qvalueCutoff = 0.2,
readable = TRUE)
# other categories (MF, CC)
go_enrichment_pp_MF <- enrichGO(gene = entrez_ids_pp$ENTREZID,
OrgDb = org.Hs.eg.db,
ont = "MF", #"MF" for Molecular Functions
pAdjustMethod = "BH",
pvalueCutoff = 0.05,
qvalueCutoff = 0.2,
readable = TRUE)
go_enrichment_pp_CC <- enrichGO(gene = entrez_ids_pp$ENTREZID,
OrgDb = org.Hs.eg.db,
ont = "CC", #"CC" for Cellular Components
pAdjustMethod = "BH",
pvalueCutoff = 0.05,
qvalueCutoff = 0.2,
readable = TRUE)
# Visualize for GO biological processes pathways
barplot(go_pp_enrichment, showCategory = 10, title = "GO Biological Processes Enrichment")

dotplot(go_pp_enrichment, showCategory = 10, title = "GO Biological Processes Enrichment")

# Use heatplot
heatplot(go_pp_enrichment, showCategory = 10)

#network plot
cnetplot(go_pp_enrichment, showCategory = 4, title = "Gene-Concept Network for Biological Processes",
max.overlaps = 100, node_label_size = 3, label_fontsize = 8) +
theme(axis.text.x = element_text(size = 10),
axis.text.y = element_text(size = 10),
plot.title = element_text(size = 14, face = "bold"))

#decided on the number 4 for the categories, as more overwhelms the plot and data points were unlabeled
# Visualize MF, CC
#molecular functions
dotplot(go_enrichment_pp_MF, showCategory = 10, title = "GO Molecular Functions Enrichment")

#cellular components
dotplot(go_enrichment_pp_CC, showCategory = 10, title = "GO Cellular Components Enrichment")

For specifically bad-responders/ targets associated with short
survival group:
#subset the data, keep only upregulated features in short survival group
subset_pp <- subset(significant_pp_results, difference.long.vs.short > 0)
#clean the data - ready for GO pathway enrichment
clean_subset_pp <- unique(sapply(strsplit(subset_pp$X, "\\("), `[`, 1))
# Convert these kinase names to Entrez IDs
en_ids_pp <- bitr(clean_subset_pp, fromType = "SYMBOL", toType = "ENTREZID", OrgDb = org.Hs.eg.db)
'select()' returned 1:1 mapping between keys and columns
Warning in bitr(clean_subset_pp, fromType = "SYMBOL", toType = "ENTREZID", :
9.05% of input gene IDs are fail to map...
#GO pathway enrichment
go_pp_p_enrichment <- enrichGO(gene = en_ids_pp$ENTREZID,
OrgDb = org.Hs.eg.db,
ont = "BP", # "BP" for Biological Processes
pAdjustMethod = "BH",
pvalueCutoff = 0.05,
qvalueCutoff = 0.2,
readable = TRUE)
#Plots
barplot(go_pp_p_enrichment, showCategory = 10, title = "GO Biological Processes enriched in short survival group")

dotplot(go_pp_p_enrichment, showCategory = 10, title = "GO Biological Processes enriched in short survival group")

heatplot(go_pp_p_enrichment, showCategory = 10)

#network plot
cnetplot(go_pp_p_enrichment, showCategory = 4, title = "Gene-Concept Network for Biological Processes enriched in short survival group",
max.overlaps = 100, node_label_size = 3, label_fontsize = 8) +
theme(axis.text.x = element_text(size = 10),
axis.text.y = element_text(size = 10),
plot.title = element_text(size = 14, face = "bold"))

#decided on 4 to not overwhelm the network plot
Using gprofiler2 / using all significant differentially expressed
features:
#gProfiler enrichment analysis
gostres_pp <- gost(query = entrez_ids_pp$ENTREZID,
organism = "hsapiens",
sources = c("GO:BP", "GO:MF", "GO:CC", "KEGG", "REAC", "WP"),
significant = TRUE,
correction_method = "fdr",
user_threshold = 0.05)
# View results
head(gostres_pp$result)
# Plot results
gostplot(gostres_pp, capped = TRUE, interactive = FALSE)

# Plot for each category (GO, KEGG, REACTOME, WIKIPATHWAYS)
bp_plot_pp <- plot_results(gostres_pp$result, "GO:BP", "Top Biological Processes")
mf_plot_pp <- plot_results(gostres_pp$result, "GO:MF", "Top Molecular Functions")
cc_plot_pp <- plot_results(gostres_pp$result, "GO:CC", "Top Cellular Components")
reac_plot_pp <- plot_results(gostres_pp$result, "REAC", "Top Reactome Pathways")
kegg_plot_pp <- plot_results(gostres_pp$result, "KEGG", "Top KEGG Pathways")
wp_plot_pp <- plot_results(gostres_pp$result, "WP", "Top WikiPathways")
# Print plots
print(bp_plot_pp)

print(mf_plot_pp)

print(cc_plot_pp)

print(reac_plot_pp)

print(kegg_plot_pp) #No KEGG pathways identified

print(wp_plot_pp)

PROTEIN QUANTIFICATION
# Filter protein quantification data
prot_quant_filtered <- prot_quant_data %>%
dplyr::select(X, all_of(short_samples), all_of(long_samples))
dim(prot_quant_filtered)
[1] 9537 41
Pre-processing steps:
# Boxplot before preprocessing
boxplot(prot_quant_filtered[, -1], las = 3, main = "Protein quantification Data Distribution Before Preprocessing", cex.main = 2)

# filtering out low counts
keep_prot_quant <- rowSums(prot_quant_filtered[, -1] >= 10) >= 3
prot_quant_filtered <- prot_quant_filtered[keep_prot_quant,]
# Log2 transformation
log2_transformed <- prot_quant_filtered
log2_transformed[, -1] <- log2(prot_quant_filtered[, -1] + 1)
# Quantile normalization
quantile_normalized <- log2_transformed
quantile_normalized[, -1] <- normalize.quantiles(as.matrix(log2_transformed[, -1]))
# Scaling (centering and scaling)
scaled <- quantile_normalized
scaled[, -1] <- scale(quantile_normalized[, -1], center = TRUE, scale = TRUE)
# Create the final preprocessed dataset
prot_quant_final <- scaled
# Boxplot after preprocessing
boxplot(prot_quant_final[, -1], las = 3, main = "Protein quantification Data Distribution After Preprocessing (Log2, Quantile Normalization, Scaling)", cex.main = 2)

NA
NA
Differential expression analysis:
# Perform differential expression analysis
df.limma.quant <- compare.by.limma(prot_quant_final, long_samples, short_samples)
# Define the p-value threshold for significance
p_value_threshold <- 0.05
# Filter significant results based on p-value
significant_pq_results <- df.limma.quant[df.limma.quant$pvalues < p_value_threshold, ]
# Print significant results
print(significant_pq_results)
# Order the significant results by absolute differential expression / most expressed but also pvalue <0.05
significant_pq_res <- significant_pq_results[order(abs(significant_pq_results$difference.long.vs.short), decreasing = TRUE), ]
# View the top 10 most significant hits
top_significant_pq <- head(significant_pq_res, 10)
#Print top 10
print(top_significant_pq)
NA
#volcano plot for differential expression results
ggplot(df.limma.quant, aes(x = difference.long.vs.short, y = -log10(pvalues))) +
geom_point(aes(color = pvalues < pval_threshold)) +
theme_minimal() +
labs(title = "Volcano Plot for Protein Quantification Data",
x = "Log2 Fold Change",
y = "-log10(p-value)") +
geom_text_repel(data = top_significant_pq, #on text the top 10 results
aes(label = X),
size = 3,
max.overlaps = Inf) + # Use Inf to avoid filtering out top 5
scale_color_manual(values = c("red", "blue"), name = "pvalues < 0.05") +
theme(legend.position = "right")

Pathway enrichment analysis:
GO Enrichment
# Extract UniProt identifiers from the significant results
uniprot_ids <- significant_pq_results$X
# Extract gene symbols from phosphoprotein IDs - they are in the format GENE_HUMAN
significant_pq <- unique(gsub("_HUMAN", "", uniprot_ids))
# Convert gene symbols to Entrez IDs
entrez_ids_pq <- bitr(significant_pq, fromType = "SYMBOL", toType = "ENTREZID", OrgDb = org.Hs.eg.db)
'select()' returned 1:1 mapping between keys and columns
Warning in bitr(significant_pq, fromType = "SYMBOL", toType = "ENTREZID", :
50.59% of input gene IDs are fail to map...
#50.59% of input gene IDs are fail to map...
#tried to use the bitr_kegg function to convert UniProt IDs to Entrez IDs: 100% failed to map
# Perform GO enrichment analysis
go_pq_enrichment <- enrichGO(gene = entrez_ids_pq$ENTREZID,
OrgDb = org.Hs.eg.db,
ont = "BP", # "BP" for Biological Processes
pAdjustMethod = "none",
pvalueCutoff = 0.01,
qvalueCutoff = 0.2,
readable = TRUE)
# other categories (MF, CC)
go_enrichment_pq_MF <- enrichGO(gene = entrez_ids_pq$ENTREZID,
OrgDb = org.Hs.eg.db,
ont = "MF", #molecular function
pAdjustMethod = "BH",
pvalueCutoff = 0.05,
qvalueCutoff = 0.2,
readable = TRUE)
#used unadjusted for these to have some results
go_enrichment_pq_CC <- enrichGO(gene = entrez_ids_pq$ENTREZID,
OrgDb = org.Hs.eg.db,
ont = "CC", #cellular components
pAdjustMethod = "none",
pvalueCutoff = 0.01,
qvalueCutoff = 0.2,
readable = TRUE)
# Visualize for GO biological processes pathways
barplot(go_pq_enrichment, showCategory = 10, title = "GO Biological Processes Enrichment")

dotplot(go_pq_enrichment, showCategory = 10, title = "GO Biological Processes Enrichment")

# Use heatplot
heatplot(go_pq_enrichment, showCategory = 10)

#network plot
cnetplot(go_pq_enrichment, showCategory = 4, title = "Gene-Concept Network for Biological Processes",
max.overlaps = 100, node_label_size = 3, label_fontsize = 8) +
theme(axis.text.x = element_text(size = 10),
axis.text.y = element_text(size = 10),
plot.title = element_text(size = 14, face = "bold"))

#decided on the number 4 for the categories, as higher number overwhelms the plot and data points were unlabeled
# Visualize MF, CC
dotplot(go_enrichment_pq_CC, showCategory = 10, title = "GO Cellular Components Enrichment")

For specifically bad-responders/ targets associated with short
survival group:
#subset the results, keeping only the features upregulared in the short survival group
subset_pq <- subset(significant_pq_results, difference.long.vs.short > 0)
#clean the data - ready for the GO enrichment analysis
clean_subset_pq <- unique(gsub("_HUMAN", "", subset_pq$X))
# Convert these kinase names to Entrez IDs
en_ids_pq <- bitr(clean_subset_pq, fromType = "SYMBOL", toType = "ENTREZID", OrgDb = org.Hs.eg.db)
'select()' returned 1:1 mapping between keys and columns
Warning in bitr(clean_subset_pq, fromType = "SYMBOL", toType = "ENTREZID", :
59.09% of input gene IDs are fail to map...
#GO enrichment
go_pq_p_enrichment <- enrichGO(gene = en_ids_pq$ENTREZID,
OrgDb = org.Hs.eg.db,
ont = "BP", # "BP" for Biological Processes
pAdjustMethod = "BH",
pvalueCutoff = 0.05,
qvalueCutoff = 0.2,
readable = TRUE)
#Plots
barplot(go_pq_p_enrichment, showCategory = 10, title = "GO Biological Processes enriched in short survival group")

dotplot(go_pq_p_enrichment, showCategory = 10, title = "GO Biological Processes enriched in short survival group")

heatplot(go_pq_p_enrichment, showCategory = 10)

#network plot
cnetplot(go_pq_p_enrichment, showCategory = 5, title = "Gene-Concept Network for Biological Processes",
max.overlaps = 100, node_label_size = 3, label_fontsize = 8) +
theme(axis.text.x = element_text(size = 10),
axis.text.y = element_text(size = 10),
plot.title = element_text(size = 14, face = "bold"))

#decided on 5 to not overwhelm the plot
Using gprofiler2 / used all the significant differentially expressed
results:
#gost function
gostres_pq <- gost(query = significant_pq,
organism = "hsapiens",
sources = c("GO:BP", "GO:MF", "GO:CC", "KEGG", "REAC", "WP"),
significant = TRUE,
correction_method = "fdr",
user_threshold = 0.05)
# View results
head(gostres_pq$result)
# Plot
gostplot(gostres_pq, capped = TRUE, interactive = FALSE)

# Plot for each category (GO, KEGG, REACTOME, WIKIPATHWAYS)
bp_plot_pq <- plot_results(gostres_pq$result, "GO:BP", "Top Biological Processes")
mf_plot_pq <- plot_results(gostres_pq$result, "GO:MF", "Top Molecular Functions")
cc_plot_pq <- plot_results(gostres_pq$result, "GO:CC", "Top Cellular Components")
reac_plot_pq <- plot_results(gostres_pq$result, "REAC", "Top Reactome Pathways")
kegg_plot_pq <- plot_results(gostres_pq$result, "KEGG", "Top KEGG Pathways")
wp_plot_pq <- plot_results(gostres_pq$result, "WP", "Top WikiPathways")
# Print plots
print(bp_plot_pq)

print(mf_plot_pq)

print(cc_plot_pq)

print(reac_plot_pq) #No Reactome pathways identfied

print(kegg_plot_pq) #No KEGG pathways identfied

print(wp_plot_pq) #No WikiPathways pathways identfied

KSEA data:
# Filter KSEA data
KSEA_filtered <- ksea_data %>%
dplyr::select(X, all_of(short_samples), all_of(long_samples))
dim(KSEA_filtered)
[1] 536 41
Pre-processing steps:
need to first perform this step, as data contains
missing(NA)/non-numeric values
# Replace zeros and negative values to avoid issues with log2
#a small constant was used to replace zeros and negative values
KSEA_filtered[, -1] <- apply(KSEA_filtered[, -1], 2, function(x) {
x[x <= 0] <- min(x[x > 0], na.rm = TRUE) / 10 # small constant to handle zeros or negative values
return(x)
})
# Boxplot before preprocessing to check distribution
boxplot(KSEA_filtered[, -1], las = 3, main = "KSEA Data Distribution Before Preprocessing", cex.main = 2)

#filtered, but with a lower threshold
KSEA_filtered <- KSEA_filtered[rowSums(KSEA_filtered[, -1] > 1) >= 2, ]
# Log2 transformation
log2_transformed <- KSEA_filtered
log2_transformed[, -1] <- log2(KSEA_filtered[, -1] + 1)
# Quantile normalization
quantile_normalized <- log2_transformed
quantile_normalized[, -1] <- normalize.quantiles(as.matrix(log2_transformed[, -1]))
# Scaling (centering and scaling)
scaled <- quantile_normalized
scaled[, -1] <- scale(as.matrix(quantile_normalized[, -1]), center = TRUE, scale = TRUE)
# Create the final preprocessed dataset
KSEA_final <- scaled
# Boxplot after preprocessing
boxplot(KSEA_final[, -1], las = 3, main = "KSEA Data Distribution After Preprocessing (Log2, Quantile Normalization, Scaling)", cex.main = 2)

Differential expression analysis:
# Perform differential expression analysis
df.limma.ksea <- compare.by.limma(KSEA_final, long_samples, short_samples)
# Define the p-value threshold for significance
p_value_threshold <- 0.05
# Filter significant results based on p-value
significant_ksea_results <- df.limma.ksea[df.limma.ksea$pvalues < p_value_threshold, ]
# Print significant results
print(significant_ksea_results)
# Order the significant results by absolute differential expression / most expressed but also pvalue <0.05
significant_ksea_res <- significant_ksea_results[order(abs(significant_ksea_results$difference.long.vs.short), decreasing = TRUE), ]
# View the top most significant hits
top_significant_ksea <- head(significant_ksea_res, 10)
#print top 10
print(top_significant_ksea)
NA
#volcano plot of differential expression results
ggplot(df.limma.ksea, aes(x = difference.long.vs.short, y = -log10(pvalues))) +
geom_point(aes(color = pvalues < pval_threshold)) +
theme_minimal() +
labs(title = "Volcano Plot for KSEA Data",
x = "Log2 Fold Change",
y = "-log10(p-value)") +
geom_text_repel(data = top_significant_ksea, #top 10 results displayed in the plot
aes(label = X),
size = 3,
max.overlaps = Inf) + # Use Inf to avoid filtering out top 5
scale_color_manual(values = c("red", "blue"), name = "pvalues < 0.05") +
theme(legend.position = "right")

Pathway enrichent analysis:
GO Enrichment
# Have to create a list to insert to pathway enrichment analysis
# Extract individual kinase names from the pairs
individual_kinases <- unique(unlist(strsplit(significant_ksea_results$X, "\\.")))
# Remove unwanted terms, mainly signor, or edges
individual_kinases <- individual_kinases[!individual_kinases %in% c("signor", "edges")]
# There is this "MAPK1_3" on the list, which is the MAPK1 and the MAPK3
individual_kinases <- c(individual_kinases, "MAPK1", "MAPK3")
# Convert these kinase names to Entrez IDs
kinase_entrez_ids_individual <- bitr(individual_kinases, fromType = "SYMBOL", toType = "ENTREZID", OrgDb = org.Hs.eg.db)
#10% says was not mapped, but it was the "MAPK1_3", so everything else was mapped successfully
#perform GO enrichment
go_ksea_enrichment <- enrichGO(gene = kinase_entrez_ids_individual$ENTREZID,
OrgDb = org.Hs.eg.db,
ont = "BP", # "BP" for Biological Processes
pAdjustMethod = "BH",
pvalueCutoff = 0.05,
qvalueCutoff = 0.2,
readable = TRUE)
# other categories (MF, CC)
go_enrichment_ksea_MF <- enrichGO(gene = kinase_entrez_ids_individual$ENTREZID,
OrgDb = org.Hs.eg.db,
ont = "MF", #molecular functions
pAdjustMethod = "BH",
pvalueCutoff = 0.05,
qvalueCutoff = 0.2,
readable = TRUE)
go_enrichment_ksea_CC <- enrichGO(gene = kinase_entrez_ids_individual$ENTREZID,
OrgDb = org.Hs.eg.db,
ont = "CC", #cellular components
pAdjustMethod = "BH",
pvalueCutoff = 0.05,
qvalueCutoff = 0.2,
readable = TRUE)
# Visualize for GO biological processes pathways
barplot(go_ksea_enrichment, showCategory = 10, title = "GO Biological Processes Enrichment")

dotplot(go_ksea_enrichment, showCategory = 10, title = "GO Biological Processes Enrichment")

# Use heatplot
heatplot(go_ksea_enrichment, showCategory = 10)

NA
NA
#network plot
cnetplot(go_ksea_enrichment, showCategory = 5, title = "Gene-Concept Network for Biological Processes",
max.overlaps = 100, node_label_size = 3, label_fontsize = 8) +
theme(axis.text.x = element_text(size = 10),
axis.text.y = element_text(size = 10),
plot.title = element_text(size = 14, face = "bold"))

#decided on 5 to not overwhelm the plot
# Visualize MF, CC
dotplot(go_enrichment_ksea_MF, showCategory = 10, title = "GO Molecular Functions Enrichment")

dotplot(go_enrichment_ksea_CC, showCategory = 10, title = "GO Cellular Components Enrichment")

For specifically bad-responders/ targets associated with short
survival outcomes group:
# Subset the data, keeping only the significant features upregulated in the short survival group
subset_ksea <- subset(significant_ksea_results, difference.long.vs.short > 0)
# Clean the data, ready for anlalysis
subset_ksea <- unique(unlist(strsplit(subset_ksea$X, "\\.")))
# Remove the unwanted terms
subset_ksea <- subset_results4[!subset_ksea %in% c("signor", "edges")]
#"MINK1" was not included so I added it
subset_ksea <- c(subset_ksea, "MINK1")
# Convert these kinase names to Entrez IDs
en_ids_ksea <- bitr(subset_ksea, fromType = "SYMBOL", toType = "ENTREZID", OrgDb = org.Hs.eg.db)
'select()' returned 1:1 mapping between keys and columns
Warning in bitr(subset_ksea, fromType = "SYMBOL", toType = "ENTREZID", OrgDb = org.Hs.eg.db) :
11.11% of input gene IDs are fail to map...
#only "MAPK1_3" not mapped, but MAPK1 and MAPK3 mapped
#GO enrichment
go_ksea_p_enrichment <- enrichGO(gene = en_ids_ksea$ENTREZID,
OrgDb = org.Hs.eg.db,
ont = "BP", # "BP" for Biological Processes
pAdjustMethod = "BH",
pvalueCutoff = 0.05,
qvalueCutoff = 0.2,
readable = TRUE)
#Plots
barplot(go_ksea_p_enrichment, showCategory = 10, title = "GO Biological Processes enriched in short survival group")

dotplot(go_ksea_p_enrichment, showCategory = 10, title = "GO Biological Processes enriched in short survival group")

heatplot(go_ksea_p_enrichment, showCategory = 10)

#network plot
cnetplot(go_ksea_p_enrichment, showCategory = 5, title = "Gene-Concept Network for Biological Processes enriched in short survival group",
max.overlaps = 100, node_label_size = 3, label_fontsize = 8) +
theme(axis.text.x = element_text(size = 10),
axis.text.y = element_text(size = 10),
plot.title = element_text(size = 14, face = "bold"))

#decided on 5 to not overwhelm the plot
Using gprofiler2 / using all significant differentially expressed
results:
#Enrichment analysis
gostres_ksea <- gost(query = kinase_entrez_ids_individual$ENTREZID,
organism = "hsapiens",
sources = c("GO:BP", "GO:MF", "GO:CC", "KEGG", "REAC", "WP"),
significant = TRUE,
correction_method = "fdr",
user_threshold = 0.05)
#View results
head(gostres_ksea$result)
#Plot
gostplot(gostres_ksea, capped = TRUE, interactive = FALSE)

# Plot for each category (GO, KEGG, REACTOME, WIKIPATHWAYS)
bp_plot_ksea <- plot_results(gostres_ksea$result, "GO:BP", "Top Biological Processes")
mf_plot_ksea <- plot_results(gostres_ksea$result, "GO:MF", "Top Molecular Functions")
cc_plot_ksea <- plot_results(gostres_ksea$result, "GO:CC", "Top Cellular Components")
reac_plot_ksea <- plot_results(gostres_ksea$result, "REAC", "Top Reactome Pathways")
kegg_plot_ksea <- plot_results(gostres_ksea$result, "KEGG", "Top KEGG Pathways")
wp_plot_ksea <- plot_results(gostres_ksea$result, "WP", "Top WikiPathways")
# Print plots
print(bp_plot_ksea)

print(mf_plot_ksea)

print(cc_plot_ksea)

print(reac_plot_ksea)

print(kegg_plot_ksea)

print(wp_plot_ksea)

RNA data:
#Filter for samples that exist in the RNA dataset
rna_short_samples <- intersect(short_samples, colnames(rna_data))
rna_long_samples <- intersect(long_samples, colnames(rna_data))
rna_filtered <- rna_data %>%
dplyr::select(X, all_of(rna_short_samples), all_of(rna_long_samples))
dim(rna_filtered)
[1] 34975 30
Pre-processing steps:
#convert data to DESeq2 format
dds <- DESeqDataSetFromMatrix(countData = as.matrix(rna_filtered[, -1]),
colData = data.frame(condition = factor(c(rep("short", length(rna_short_samples)),
rep("long", length(rna_long_samples))))),
design = ~ condition)
#Assign rownames to dds object
rownames(dds) <- rna_filtered$X
#Filter out low count genes
keep <- rowSums(counts(dds) >= 10) >= 3
dds <- dds[keep,]
# Run DESeq2 to normalize the data
dds <- DESeq(dds)
estimating size factors
estimating dispersions
gene-wise dispersion estimates
mean-dispersion relationship
final dispersion estimates
fitting model and testing
-- replacing outliers and refitting for 1635 genes
-- DESeq argument 'minReplicatesForReplace' = 7
-- original counts are preserved in counts(dds)
estimating dispersions
fitting model and testing
normalized_counts <- counts(dds, normalized = TRUE)
#Log2 transform the normalized counts
log2_normalized_counts <- log2(normalized_counts + 1)
#Scale and centre
scaled_counts <- scale(log2_normalized_counts, center = TRUE, scale = TRUE)
# Convert back to a data frame for easy/better handling
scaled_counts_df <- as.data.frame(scaled_counts)
# Update gene identifiers if they were in rownames
rownames(scaled_counts_df) <- rownames(log2_normalized_counts)
#new combined data frame
rna_scaled_final <- data.frame(gene = rownames(scaled_counts_df), scaled_counts_df)
# Boxplot to visualize the data distribution (before and after)
# Before
boxplot(rna_filtered[, -1], las = 3, main = "RNA-seq Data Distribution before Preprocessing", cex.main = 2)

#After
boxplot(rna_scaled_final[, -1], las = 3, main = "RNA-seq Data Distribution after Preprocessing steps", cex.main = 2)

NA
NA
Differential expression analysis:
# Perform differential analysis
df.limma.rna <- compare.by.limma(rna_scaled_final, rna_long_samples, rna_short_samples)
# Filter significant results based on p-value
significant_rna_results <- df.limma.rna[df.limma.rna$pvalues < p_value_threshold, ]
#View all significant results
print(significant_rna_results)
# Order the significant results by absolute differential expression / most expressed but also pvalue <0.05
significant_rna_res <- significant_rna_results[order(abs(significant_rna_results$difference.long.vs.short), decreasing = TRUE), ]
# View the top 10 most significant hits
top_significant_rna <- head(significant_rna_res, 20)
#Print top 10
print(top_significant_rna)
NA
# volcano plot for differential expression results
ggplot(df.limma.rna, aes(x = difference.long.vs.short, y = -log10(pvalues))) +
geom_point(aes(color = pvalues < pval_threshold)) +
theme_minimal() +
labs(title = "Volcano Plot for RNA Data",
x = "Log2 Fold Change",
y = "-log10(p-value)") +
geom_text_repel(data = top_significant_rna, #displayed are the top 20 instead of 10 this time, to also have a feature upregulated in the short survival side
aes(label = X),
size = 3,
max.overlaps = Inf) + # Use Inf to avoid filtering out top 5
scale_color_manual(values = c("red", "blue"), name = "pvalues < 0.05") +
theme(legend.position = "right")

PATHWAY ENRICHMENT ANALYSIS
GO Enrichment:
#Extract significant genes
gene_list_rna <- significant_rna_results$X
#remove everything after the dot
#the presence of additional suffixes or non-standard formats in the gene names, such as the use of dots (e.g., AC073072.1 or EAF1.AS1). These symbols might represent different isoforms, transcript variants, or other non-canonical identifiers that aren't directly recognized in the org.Hs.eg.db database for Entrez ID conversion. - so removed to keep a clean data for pathway enrichment
gene_list_rna_cleaned <- gsub("\\..*", "", gene_list_rna)
#Convert gene symbols to Entrez IDs
entrez_ids_rna <- bitr(gene_list_rna_cleaned, fromType = "SYMBOL", toType = "ENTREZID", OrgDb = org.Hs.eg.db)
'select()' returned 1:1 mapping between keys and columns
Warning in bitr(gene_list_rna_cleaned, fromType = "SYMBOL", toType = "ENTREZID", :
6.57% of input gene IDs are fail to map...
#6.57% of input gene IDs are fail to map...
#GO enrichment
#used unadjusted pvalue, but still no results
go_RNA_enrichment <- enrichGO(gene = entrez_ids_rna$ENTREZID,
OrgDb = org.Hs.eg.db,
ont = "BP", # "BP" for Biological Processes
pAdjustMethod = "none",
pvalueCutoff = 0.05,
qvalueCutoff = 0.2,
readable = TRUE)
# other categories (MF, CC)
#used unadjusted pvalue, but still no results
go_enrichment_RNA_MF <- enrichGO(gene = entrez_ids_rna$ENTREZID,
OrgDb = org.Hs.eg.db,
ont = "MF",
pAdjustMethod = "none",
pvalueCutoff = 0.05,
qvalueCutoff = 0.2,
readable = TRUE)
#results created
go_enrichment_RNA_CC <- enrichGO(gene = entrez_ids_rna$ENTREZID,
OrgDb = org.Hs.eg.db,
ont = "CC",
pAdjustMethod = "BH",
pvalueCutoff = 0.05,
qvalueCutoff = 0.2,
readable = TRUE)
# Visualize CC
dotplot(go_enrichment_RNA_CC, showCategory = 10, title = "GO Cellular Components Enrichment")

For specifically bad-responders/ targets associated with short
survival group:
#Filter/subset data, keeping only features upregulated in the short survival group
subset_rna <- subset(significant_rna_results, difference.long.vs.short > 0)
subset_rna <- subset_rna$X
#clean - ready for analysis
subset_rna_cleaned <- gsub("\\..*", "", subset_rna)
# Convert these kinase names to Entrez IDs
en_ids_rna <- bitr(subset_rna_cleaned, fromType = "SYMBOL", toType = "ENTREZID", OrgDb = org.Hs.eg.db)
'select()' returned 1:1 mapping between keys and columns
Warning in bitr(subset_rna_cleaned, fromType = "SYMBOL", toType = "ENTREZID", :
7.25% of input gene IDs are fail to map...
#GO enrichment
go_rna_p_enrichment <- enrichGO(gene = en_ids_rna$ENTREZID,
OrgDb = org.Hs.eg.db,
ont = "BP", # "BP" for Biological Processes
pAdjustMethod = "BH",
pvalueCutoff = 0.05,
qvalueCutoff = 0.2,
readable = TRUE)
#Plots
barplot(go_rna_p_enrichment, showCategory = 10, title = "GO Biological Processes enriched in short survival group")

dotplot(go_rna_p_enrichment, showCategory = 10, title = "GO Biological Processes enriched in short survival group")

heatplot(go_rna_p_enrichment, showCategory = 10)

#network plot
cnetplot(go_rna_p_enrichment, showCategory = 5, title = "Gene-Concept Network for Biological Processes enriched in short survival group",
max.overlaps = 100, node_label_size = 3, label_fontsize = 8) +
theme(axis.text.x = element_text(size = 10),
axis.text.y = element_text(size = 10),
plot.title = element_text(size = 14, face = "bold"))
Warning: ggrepel: 1 unlabeled data points (too many overlaps). Consider increasing max.overlaps

#decided on 5 to not overwhelm the plot
Using gprofiler2 / for all significant differentially expressed
features
gostres_RNA <- gost(query = entrez_ids_rna$ENTREZID,
organism = "hsapiens",
sources = c("GO:BP", "GO:MF", "GO:CC", "KEGG", "REAC", "WP"),
significant = TRUE,
correction_method = "fdr",
user_threshold = 0.05)
# View results
head(gostres_RNA$result)
# Plot
gostplot(gostres_RNA, capped = TRUE, interactive = FALSE)

# Plot for each category (GO, KEGG, REACTOME, WIKIPATHWAYS)
bp_plot_RNA <- plot_results(gostres_RNA$result, "GO:BP", "Top Biological Processes")
mf_plot_RNA <- plot_results(gostres_RNA$result, "GO:MF", "Top Molecular Functions")
cc_plot_RNA <- plot_results(gostres_RNA$result, "GO:CC", "Top Cellular Components")
reac_plot_RNA <- plot_results(gostres_RNA$result, "REAC", "Top Reactome Pathways")
kegg_plot_RNA <- plot_results(gostres_RNA$result, "KEGG", "Top KEGG Pathways")
wp_plot_RNA <- plot_results(gostres_RNA$result, "WP", "Top WikiPathways")
# Print plots
print(bp_plot_RNA)

print(mf_plot_RNA)

print(cc_plot_RNA)

print(reac_plot_RNA) #No reactome

print(kegg_plot_RNA) #No KEGG

print(wp_plot_RNA) #No WikiPathways

NOW FURTHER ANALYZE PATIENT INFORMATION FIND SOME DESCRIPTIVE
STATISTICS, PATIENT DEMOGRAPHIC INFORMATION:
#CHECK PATIENT INFO / KARYOTYPES
pt_short <- intersect(short_samples, pt_info$Sample_Name)
pt_long <- intersect(long_samples, pt_info$Sample_Name)
pt_info_short <- pt_info %>%
filter(Sample_Name %in% pt_short) %>%
dplyr::select(Sample_Name, Type, Gender, Disease, Stage, Karyotype, Karyotype_group, age.at.diagnosis, STATUS, SURVIVAL..YRS.)
pt_info_long <- pt_info %>%
filter(Sample_Name %in% pt_long) %>%
dplyr::select(Sample_Name, Type, Gender, Disease, Stage, Karyotype, Karyotype_group, age.at.diagnosis, STATUS, SURVIVAL..YRS.)
print(pt_info_short)
print(pt_info_long)
NA
In terms of patient demographics check the age and gender:
AGE AND GENDER
#Ensure all values are numeric / as there are some missing values in these datasets
pt_info_short$age.at.diagnosis <- as.numeric(as.character(pt_info_short$age.at.diagnosis))
pt_info_long$age.at.diagnosis <- as.numeric(as.character(pt_info_long$age.at.diagnosis))
#calculate mean age
mean_age_short <- mean(pt_info_short$age.at.diagnosis, na.rm = TRUE) #na.rm as there are some missing values in these datasets
mean_age_long <- mean(pt_info_long$age.at.diagnosis, na.rm = TRUE)
#Calculate gender overall number for the short survival group
gender_count_short <- pt_info_short %>%
group_by(Gender) %>%
summarize(Count = n())
#Calculate gender overall number for the long survival group
gender_count_long <- pt_info_long %>%
group_by(Gender) %>%
summarize(Count = n())
# Print results
#short
cat("Mean Age:", mean_age_short, "\n")
Mean Age: 61.24
print(gender_count_short)
#long
cat("Mean Age:", mean_age_long, "\n")
Mean Age: 45.23889
print(gender_count_long)
NA
NA
KARYOTYPE GROUP: These different types are found in these patients:
“MLL”, “Complex”, “del17”, “del5”, “del7”, “t(3;3)”, “t(8;16)”
# Calculate the count of each karyotype group - short survival group
karyotype_count_short <- pt_info_short %>%
filter(Karyotype_group %in% c("MLL", "Complex", "del17", "del5", "del7", "t(3;3)", "t(8;16)")) %>%
group_by(Karyotype_group) %>%
summarize(Count = n())
# the same for the long survival group
karyotype_count_long <- pt_info_long %>%
filter(Karyotype_group %in% c("MLL", "Complex", "del17", "del5", "del7", "t(3;3)", "t(8;16)")) %>%
group_by(Karyotype_group) %>%
summarize(Count = n())
# Print results
#short
print(karyotype_count_short)
#long
print(karyotype_count_long)
NA
Some descriptive statistics regarding the patients’ survival years -
overall and the two groups:
#descriptive statistics for the whole dataset (all patients)
# Calculate mean
overall_survival_stats <- patients_list %>%
summarise(
mean_survival = mean(`SURVIVAL..YRS.`),
median_survival = median(`SURVIVAL..YRS.`),
min_survival = min(`SURVIVAL..YRS.`),
max_survival = max(`SURVIVAL..YRS.`),
range_survival = max(`SURVIVAL..YRS.`) - min(`SURVIVAL..YRS.`)
)
# Print
print(overall_survival_stats)
NA
#descriptive statistics for the short survival group - minimum value, max, median survival, and range
#calculate all
short_survival_stats <- short_survivals %>%
summarise(
mean_survival = mean(`SURVIVAL..YRS.`),
median_survival = median(`SURVIVAL..YRS.`),
min_survival = min(`SURVIVAL..YRS.`),
max_survival = max(`SURVIVAL..YRS.`),
range_survival = max(`SURVIVAL..YRS.`) - min(`SURVIVAL..YRS.`)
)
# Print
print(short_survival_stats)
NA
# descriptive statistics for the long survival group -minimum value, max, median survival, and range
#calculate all
long_survival_stats <- long_survivals %>%
summarise(
mean_survival = mean(`SURVIVAL..YRS.`),
median_survival = median(`SURVIVAL..YRS.`),
min_survival = min(`SURVIVAL..YRS.`),
max_survival = max(`SURVIVAL..YRS.`),
range_survival = max(`SURVIVAL..YRS.`) - min(`SURVIVAL..YRS.`)
)
#print
print(long_survival_stats)
NA
Combine now all of them into a dataframe to create a graph to compare
them, each statistic: minimum value, max, median survival, and range
:
#combine all survival statistics into one dataframe
combined_stats <- data.frame(
Group = c("Overall", "Short", "Long"),
Mean_Survival = c(overall_survival_stats$mean_survival, short_survival_stats$mean_survival, long_survival_stats$mean_survival),
Median_Survival = c(overall_survival_stats$median_survival, short_survival_stats$median_survival, long_survival_stats$median_survival),
Min_Survival = c(overall_survival_stats$min_survival, short_survival_stats$min_survival, long_survival_stats$min_survival),
Max_Survival = c(overall_survival_stats$max_survival, short_survival_stats$max_survival, long_survival_stats$max_survival),
Range_Survival = c(overall_survival_stats$range_survival, short_survival_stats$range_survival, long_survival_stats$range_survival)
)
#convert data to long format - helps with the plotting
long_stats <- tidyr::pivot_longer(combined_stats, cols = -Group, names_to = "Statistic", values_to = "Value")
#plot to view and compare all
ggplot(long_stats, aes(x = Group, y = Value, fill = Statistic)) +
geom_bar(stat = "identity", position = "dodge") + # Ensure the + is at the end of this line
labs(title = "Comparison of Survival Statistics Across the Groups",
x = "Group",
y = "Survival (Years)",
fill = "Statistic") +
theme_minimal() +
scale_fill_brewer(palette = "Set3")

NA
NA
Now, some additional descriptive statistics for each dataset - based
on the differential expression analysis results: - overall number of
features - overall number of features upregulated in the short survival
group - overall number of features upregulated in the long survival
group
# Total number of features in each dataset before filtering for significance (p-value <0.05)
total_phosphoproteins <- nrow(df.limma.phospho)
total_phosphorylation_sites <- nrow(df.limma.pp)
total_proteins <- nrow(df.limma.quant)
total_ksea <- nrow(df.limma.ksea)
total_rna <- nrow(df.limma.rna)
# Number of significantly differentially expressed and statistically significant (p-value<0.05) features
num_sig_phosphoproteins <- nrow(significant_phospho_results)
num_sig_phosphorylation_sites <- nrow(significant_pp_results)
num_sig_proteins <- nrow(significant_pq_results)
num_sig_ksea <- nrow(significant_ksea_results)
num_sig_rna <- nrow(significant_rna_results)
# Number of increased and decreased features
num_increased_phosphoproteins <- sum(significant_phospho_results$difference.long.vs.short > 0)
num_decreased_phosphoproteins <- sum(significant_phospho_results$difference.long.vs.short < 0)
num_increased_phosphorylation_sites <- sum(significant_pp_results$difference.long.vs.short > 0)
num_decreased_phosphorylation_sites <- sum(significant_pp_results$difference.long.vs.short < 0)
num_increased_proteins <- sum(significant_pq_results$difference.long.vs.short > 0)
num_decreased_proteins <- sum(significant_pq_results$difference.long.vs.short < 0)
num_increased_ksea <- sum(significant_ksea_results$difference.long.vs.short > 0)
num_decreased_ksea <- sum(significant_ksea_results$difference.long.vs.short < 0)
num_increased_rna <- sum(significant_rna_results$difference.long.vs.short > 0)
num_decreased_rna <- sum(significant_rna_results$difference.long.vs.short < 0)
Now add the increased and decreased from each dataset to create a
plot to compare:
# have them all as a dataframe for the plot
data_all <- data.frame(
Dataset = rep(c("Phosphoproteins", "pp-index", "Proteins", "KSEA", "RNA"), each = 2),
Expression = rep(c("Increased", "Decreased"), 5),
Count = c(
num_increased_phosphoproteins, num_decreased_phosphoproteins,
num_increased_phosphorylation_sites, num_decreased_phosphorylation_sites,
num_increased_proteins, num_decreased_proteins,
num_increased_ksea, num_decreased_ksea,
num_increased_rna, num_decreased_rna
)
)
#create the plot
ggplot(data_all, aes(x = Dataset, y = Count, fill = Expression)) +
geom_bar(stat = "identity", position = "dodge") +
theme_minimal() +
labs(title = "Number of increased and decreased significant features",
x = "Datasets",
y = "Number of Features") +
scale_fill_manual(values = c("Increased" = "skyblue", "Decreased" = "salmon")) +
theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
geom_text(aes(label = Count),
position = position_dodge(width = 0.9),
vjust = -0.5,
size = 3.5) # Adjust the size as needed

Now, find the common targets (significant differentially expressed
features) between datasets:
#all significant results
phospho <- significant_ph
ppIndex <- significant_pp
proteinq <- significant_pq
KSEA <- individual_kinases
RNA <- gene_list_rna_cleaned
# Find common features between each
#phospho
common_phospho_pp <- intersect(phospho, ppIndex)
common_phospho_protein <- intersect(phospho, proteinq)
common_phospho_KSEA <- intersect(phospho, KSEA)
common_phospho_RNA <- intersect(phospho, RNA)
#pp-index
common_pp_protein <- intersect(ppIndex, proteinq)
common_pp_KSEA <- intersect(ppIndex, KSEA)
common_pp_RNA <- intersect(ppIndex, RNA)
#protein quantification
common_protein_KSEA <- intersect(proteinq, KSEA)
common_protein_RNA <- intersect(proteinq, RNA)
#last one- RNA
common_KSEA_RNA <- intersect(KSEA, RNA)
#To see if any element is common across all datasets
common_all <- Reduce(intersect, list(phospho, ppIndex, proteinq, KSEA, RNA))
install.packages("VennDiagram")
library(VennDiagram)
# Venn diagram created to better view the common results / - using the significant_results
venn.plot <- venn.diagram(
x = list(
Phosphoproteins = phospho,
"pp-index" = ppIndex,
Proteins = proteinq,
KSEA = KSEA,
RNA = RNA
),
filename = NULL, # Set to NULL to plot directly
fill = c("red", "blue", "green", "yellow", "purple"), #colors to better view the results
alpha = 0.5,
cex = 1.5,
cat.cex = 1.5,
cat.pos = 0,
cat.dist = 0.05,
cat.default.pos = "outer",
rotation.degree = 0,
margin = 0.1,
lwd = 2,
lty = 'solid',
col = c("red", "blue", "green", "yellow", "purple"),
print.mode = c("raw"),
sigdigs = 2
)
#Plot the diagram
grid.newpage()
grid.draw(venn.plot)

NOW, DRUG SENSITIVITY SCORES USING THE DRUG SENSITIVITY TABLE:
#filter for only the short and long survival groups
DRUG_short_samples <- intersect(short_samples, colnames(Table_of_sDSS))
DRUG_long_samples <- intersect(long_samples, colnames(Table_of_sDSS))
table_of_sDSS_filtered_short <- Table_of_sDSS %>%
dplyr::select(drug, functional.class, mechanism.target, development.phase, all_of(DRUG_short_samples))
table_of_sDSS_filtered_long <- Table_of_sDSS %>%
dplyr::select(drug, functional.class, mechanism.target, development.phase, all_of(DRUG_long_samples))
For all of these take into account that there were missing values in
some, so function created to have everything numeric and remove such
unwanted values
First, for CDKN1B:
#For CDKN1B
# Filter for drugs targeting 'CDK' (for CDK inhibitors)
short_CDK <- table_of_sDSS_filtered_short %>% filter(grepl("CDK", mechanism.target, ignore.case = TRUE))
long_CDK <- table_of_sDSS_filtered_long %>% filter(grepl("CDK", mechanism.target, ignore.case = TRUE))
#Function used to clean and convert columns to numeric
convert_columns_to_numeric <- function(df) {
df %>%
mutate(across(starts_with("T"), function(x) {
as.numeric(gsub("[^0-9.]", "", as.character(x))) # Remove non-numeric characters before conversion
}, .names = "numeric_{col}"))
}
#apply the function to each group
short_CDK <- short_CDK %>% convert_columns_to_numeric()
long_CDK <- long_CDK %>% convert_columns_to_numeric()
# Calculate mean sensitivity score for each drug - excluding NAs/missing values
short_CDK <- short_CDK %>%
rowwise() %>%
mutate(mean_sensitivity = mean(c_across(starts_with("numeric_")), na.rm = TRUE))
long_CDK <- long_CDK %>%
rowwise() %>%
mutate(mean_sensitivity = mean(c_across(starts_with("numeric_")), na.rm = TRUE))
#then calculate overall means
mean_sensitivity_short <- mean(short_CDK$mean_sensitivity, na.rm = TRUE)
mean_sensitivity_long <- mean(long_CDK$mean_sensitivity, na.rm = TRUE)
#Print overall mean sensitivity score
print("Mean Sensitivity Scores:")
[1] "Mean Sensitivity Scores:"
print(paste("Short Survival Group: ", mean_sensitivity_short))
[1] "Short Survival Group: 4.73642857142857"
print(paste("Long Survival Group: ", mean_sensitivity_long))
[1] "Long Survival Group: 3.5827380952381"
For ACSS2:
#FOR ACSS2
#The function to clean and convert columns to numeric
convert_columns_to_numeric <- function(df) {
df %>%
mutate(across(starts_with("T"), ~as.numeric(as.character(.))))
}
#filter for the drugs interacting with ACSS2 identified in DGIb
ACSS2_short <- table_of_sDSS_filtered_short %>%
filter(drug %in% c("Docetaxel", "Gemcitabine")) %>%
convert_columns_to_numeric()
Warning: There were 3 warnings in `mutate()`.
The first warning was:
ℹ In argument: `across(starts_with("T"), ~as.numeric(as.character(.)))`.
Caused by warning:
! NAs introduced by coercion
ℹ Run ]8;;ide:run:dplyr::last_dplyr_warnings()dplyr::last_dplyr_warnings()]8;; to see the 2 remaining warnings.
ACSS2_long <- table_of_sDSS_filtered_long %>%
filter(drug %in% c("Docetaxel", "Gemcitabine")) %>%
convert_columns_to_numeric()
Warning: There was 1 warning in `mutate()`.
ℹ In argument: `across(starts_with("T"), ~as.numeric(as.character(.)))`.
Caused by warning:
! NAs introduced by coercion
# Calculate mean sensitivity score for each drug - excluding the NAs
ACSS2_short <- ACSS2_short %>%
rowwise() %>%
mutate(mean_sensitivity = mean(c_across(starts_with("T")), na.rm = TRUE))
ACSS2_long <- ACSS2_long %>%
rowwise() %>%
mutate(mean_sensitivity = mean(c_across(starts_with("T")), na.rm = TRUE))
# Calculate overall means
mean_ACSS2_short <- mean(ACSS2_short$mean_sensitivity, na.rm = TRUE)
mean_ACSS2_long <- mean(ACSS2_long$mean_sensitivity, na.rm = TRUE)
# Print overall mean sensitivity scores
print("Mean Sensitivity Scores:")
[1] "Mean Sensitivity Scores:"
print(paste("Short Survival Group: ", mean_ACSS2_short))
[1] "Short Survival Group: 11.9625"
print(paste("Long Survival Group: ", mean_ACSS2_long))
[1] "Long Survival Group: -3.72291666666667"
For CTNNB1:
#FOR CTNNB1
#Filter for the drugs interacting with CTNNB1 identified in DGIb
CTNNB1_short <- table_of_sDSS_filtered_short %>%
filter(drug %in% c("Letrozole", "Imatinib", "Triciribine", "Sorafenib", "Temsirolimus", "Lenalidomide", "Thalidomide", "AZ 3146")) %>%
convert_columns_to_numeric()
Warning: There were 3 warnings in `mutate()`.
The first warning was:
ℹ In argument: `across(starts_with("T"), ~as.numeric(as.character(.)))`.
Caused by warning:
! NAs introduced by coercion
ℹ Run ]8;;ide:run:dplyr::last_dplyr_warnings()dplyr::last_dplyr_warnings()]8;; to see the 2 remaining warnings.
CTNNB1_long <- table_of_sDSS_filtered_long %>%
filter(drug %in% c("Letrozole", "Imatinib", "Triciribine", "Sorafenib", "Temsirolimus", "Lenalidomide", "Thalidomide", "AZ 3146")) %>%
convert_columns_to_numeric()
Warning: There was 1 warning in `mutate()`.
ℹ In argument: `across(starts_with("T"), ~as.numeric(as.character(.)))`.
Caused by warning:
! NAs introduced by coercion
#Calculate mean sensitivity score for each drug - excluding NAs
CTNNB1_short <- CTNNB1_short %>%
rowwise() %>%
mutate(mean_sensitivity = mean(c_across(starts_with("T")), na.rm = TRUE))
CTNNB1_long <- CTNNB1_long %>%
rowwise() %>%
mutate(mean_sensitivity = mean(c_across(starts_with("T")), na.rm = TRUE))
#Calculate overall means
mean_CTNNB1_short <- mean(CTNNB1_short$mean_sensitivity, na.rm = TRUE)
mean_CTNNB1_long <- mean(CTNNB1_long$mean_sensitivity, na.rm = TRUE)
# Print
print("Mean Sensitivity Scores:")
[1] "Mean Sensitivity Scores:"
print(paste("Short Survival Group: ", mean_CTNNB1_short))
[1] "Short Survival Group: 2.759375"
print(paste("Long Survival Group: ", mean_CTNNB1_long))
[1] "Long Survival Group: 0.280208333333333"
For MAP4K5 - MINK1:
#FOR MAP4K5.MINK1.edges
#Filter for the drugs interacting with MAP4K5 and MINK1 identified in DGIb
MM_short <- table_of_sDSS_filtered_short %>%
filter(drug %in% c("Vandetanib", "Gefitinib", "Dasatinib anhydrous", "Cediranib", "Dovitinib", "Tozasertib", "Linifanib", "Sorafenib", "Erlotinib", "SNS-314")) %>%
convert_columns_to_numeric()
Warning: There were 5 warnings in `mutate()`.
The first warning was:
ℹ In argument: `across(starts_with("T"), ~as.numeric(as.character(.)))`.
Caused by warning:
! NAs introduced by coercion
ℹ Run ]8;;ide:run:dplyr::last_dplyr_warnings()dplyr::last_dplyr_warnings()]8;; to see the 4 remaining warnings.
MM_long <- table_of_sDSS_filtered_long %>%
filter(drug %in% c("Vandetanib", "Gefitinib", "Dasatinib anhydrous", "Cediranib", "Dovitinib", "Tozasertib", "Linifanib", "Sorafenib", "Erlotinib", "SNS-314")) %>%
convert_columns_to_numeric()
Warning: There were 4 warnings in `mutate()`.
The first warning was:
ℹ In argument: `across(starts_with("T"), ~as.numeric(as.character(.)))`.
Caused by warning:
! NAs introduced by coercion
ℹ Run ]8;;ide:run:dplyr::last_dplyr_warnings()dplyr::last_dplyr_warnings()]8;; to see the 3 remaining warnings.
#calculate mean sensitivity score for each drug - excluding NAs
MM_short <- MM_short %>%
rowwise() %>%
mutate(mean_sensitivity = mean(c_across(starts_with("T")), na.rm = TRUE))
MM_long <- MM_long %>%
rowwise() %>%
mutate(mean_sensitivity = mean(c_across(starts_with("T")), na.rm = TRUE))
#Calculate overall means
mean_MM_short <- mean(MM_short$mean_sensitivity, na.rm = TRUE)
mean_MM_long <- mean(MM_long$mean_sensitivity, na.rm = TRUE)
#Print results
print("Mean Sensitivity Scores:")
[1] "Mean Sensitivity Scores:"
print(paste("Short Survival Group: ", mean_MM_short))
[1] "Short Survival Group: 2.759375"
print(paste("Long Survival Group: ", mean_MM_long))
[1] "Long Survival Group: -0.1828125"
For PRKD1:
#FOR PRKD1
#Filter for the drugs interacting with PRKD1 identified in DGIb
PRKD1_short <- table_of_sDSS_filtered_short %>%
filter(drug %in% c("Midostaurin", "Bryostatin")) %>%
convert_columns_to_numeric()
Warning: There was 1 warning in `mutate()`.
ℹ In argument: `across(starts_with("T"), ~as.numeric(as.character(.)))`.
Caused by warning:
! NAs introduced by coercion
PRKD1_long <- table_of_sDSS_filtered_long %>%
filter(drug %in% c("Midostaurin", "Bryostatin")) %>%
convert_columns_to_numeric()
#Calculate mean sensitivity score for each drug - excluding the NAs
PRKD1_short <- PRKD1_short %>%
rowwise() %>%
mutate(mean_sensitivity = mean(c_across(starts_with("T")), na.rm = TRUE))
PRKD1_long <- PRKD1_long %>%
rowwise() %>%
mutate(mean_sensitivity = mean(c_across(starts_with("T")), na.rm = TRUE))
#Calculate overall means
mean_PRKD1_short <- mean(PRKD1_short$mean_sensitivity, na.rm = TRUE)
mean_PRKD1_long <- mean(PRKD1_long$mean_sensitivity, na.rm = TRUE)
#Print overall means
print("Mean Sensitivity Scores:")
[1] "Mean Sensitivity Scores:"
print(paste("Short Survival Group: ", mean_PRKD1_short))
[1] "Short Survival Group: 5.9"
print(paste("Long Survival Group: ", mean_PRKD1_long))
[1] "Long Survival Group: 5.3625"
To create a plot for the Results section showing all the mean drug
sensitivity score of these drugs:
#create dataframe - add all
data <- data.frame(
Feature = c("CDKN1B", "ACSS2", "CTNNB1", "MAP4K5/MINK1", "PRKD1"),
Short_Survival_Group = c(mean_sensitivity_short, mean_ACSS2_short, mean_CTNNB1_short, mean_MM_short, mean_PRKD1_short),
Long_Survival_Group = c(mean_sensitivity_long, mean_ACSS2_long, mean_CTNNB1_long, mean_MM_long, mean_PRKD1_long)
)
#have the data to long format for ggplot2
library(reshape2)
data_melted <- melt(data, id.vars = "Feature", variable.name = "Group", value.name = "Mean_Sensitivity")
# The plot for drug sensitivity
ggplot(data_melted, aes(x = Feature, y = Mean_Sensitivity, fill = Group)) +
geom_bar(stat = "identity", position = "dodge") +
geom_text(aes(label = round(Mean_Sensitivity, 2)),
position = position_dodge(width = 0.9),
vjust = -0.3,
size = 3.5) +
theme_minimal() +
labs(title = "Mean Drug Sensitivity Scores by Feature",
x = "Feature",
y = "Mean Sensitivity Score",
fill = "Group") +
theme(axis.text.x = element_text(angle = 45, hjust = 1))

NA
NA
LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQpBbmFseXNpcyBmb3IgdGhlIHJlc2VhcmNoIHByb2plY3Q6IApUaGlzIGNvbnRhaW5zOiAKCi0gVGhlIGRvd25zdHJlYW0gYW5hbHlzaXMgb2YgYWxsIHRoZSBkYXRhc2V0cyhmaWx0ZXJpbmcgb2YgcGF0aWVudHMsIHByZS1wcm9jZXNzaW5nLCBkaWZmZXJlbnRpYWwgZXhwcmVzc2lvbiwgcGF0aHdheSBlbnJpY2htZW50KSAoc3RhcnRzIGF0IGxpbmUgODkpCi0gVGhlIHBhdGllbnQgZGVtb2dyYXBoaWMgaW5mb3JtYXRpb24oc3RhcnRzIGF0IGxpbmUgMTQ3MikgCi0gVGhlIGRhdGEgbWFuaXB1bGF0aW9uIG9mIHRoZSBkaWZmZXJlbnRpYWwgZXhwcmVzc2lvbiBhbmFseXNpcyByZXN1bHRzIChzdGFydHMgYXQgbGluZSAxNjQ3KQotIFRoZSBjYWxjdWxhdGlvbiBvZiBtZWFuIGRydWcgc2Vuc2l0aXZpdHkgc2NvcmVzIG9mIHNwZWNpZmllZCBmZWF0dXJlcyAoc3RhcnRzIGF0IGxpbmUgMTgwMSkuICAKCmxvYWQgYWxsIHJlcXVpcmVkIHBhY2thZ2VzOgpgYGB7cn0KIyBJbnN0YWxsIG5lY2Vzc2FyeSBwYWNrYWdlcyBmb3IgdGhlIHByb2plY3QgCgppZiAoIXJlcXVpcmVOYW1lc3BhY2UoIkJpb2NNYW5hZ2VyIiwgcXVpZXRseSA9IFRSVUUpKQogIGluc3RhbGwucGFja2FnZXMoIkJpb2NNYW5hZ2VyIikKCmluc3RhbGwucGFja2FnZXMoYygicmVhZHhsIiwgImRwbHlyIiwgImxpbW1hIiwgImdncGxvdDIiKSkKQmlvY01hbmFnZXI6Omluc3RhbGwoYygiREVTZXEyIiwgImNsdXN0ZXJQcm9maWxlciIsICJvcmcuSHMuZWcuZGIiLCAibGltbWEiLCAiRE9TRSIpKQpCaW9jTWFuYWdlcjo6aW5zdGFsbCgicHJlcHJvY2Vzc0NvcmUiKQoKCmluc3RhbGwucGFja2FnZXMoImdncmVwZWwiKQppbnN0YWxsLnBhY2thZ2VzKCJ4ZnVuIikKCgojbGlicmFyaWVzCmxpYnJhcnkocmVhZHhsKQpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KGxpbW1hKQpsaWJyYXJ5KERFU2VxMikKbGlicmFyeShjbHVzdGVyUHJvZmlsZXIpCmxpYnJhcnkob3JnLkhzLmVnLmRiKQpsaWJyYXJ5KGxpbW1hKQpsaWJyYXJ5KERPU0UpCmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShnZ3JlcGVsKQpsaWJyYXJ5KHByZXByb2Nlc3NDb3JlKQoKaW5zdGFsbC5wYWNrYWdlcygia25pdHIiKQppbnN0YWxsLnBhY2thZ2VzKCJybWFya2Rvd24iKQoKbGlicmFyeShybWFya2Rvd24pCmxpYnJhcnkoa25pdHIpCgpgYGAKCgpgYGB7cn0KCiMgSW5zdGFsbCBncHJvZmlsZXIyICAtIGZvciBwYXRod2F5IGVucmljaGVtbnQgYW5hbHlzaXMgCmlmICghcmVxdWlyZU5hbWVzcGFjZSgiZ3Byb2ZpbGVyMiIsIHF1aWV0bHkgPSBUUlVFKSkgewogIGluc3RhbGwucGFja2FnZXMoImdwcm9maWxlcjIiKQp9CgpsaWJyYXJ5KGdwcm9maWxlcjIpCgpgYGAKCgpgYGB7cn0KIAojZGF0YXNldHMgdXNlZCAKcHJvdF9xdWFudF9kYXRhIDwtIHJlYWQuY3N2KCJwcm90X3F1YW50X3Bvb3JyaXNrX2FtbC5jc3YiKQpybmFfZGF0YSA8LSByZWFkLmNzdigiUk5Bc2VxIGJvdGggQkNJIGFuZCBGSU5OLmNzdiIpCmtzZWFfZGF0YSA8LSByZWFkLmNzdigiS1NFQSBwb29yIHJpc2sgQU1MIGRpc3QgYWxsLmNzdiIpCnBob3NwaG9wcm90ZWluX2RhdGEgPC0gcmVhZC5jc3YoInBob3NwaG9wcm90ZWluc19zdW1fcHBzaXRlc19wb29yX3Jpc2tfYW1sLmNzdiIpCnBwaW5kZXhfZGF0YSA8LSByZWFkLmNzdigicHBpbmRleF9wb29ycmlza19hbWwuY3N2IikKVGFibGVfb2Zfc0RTUyA8LSByZWFkX2V4Y2VsKCJUYWJsZV9vZl9zRFNTLnhsc3giKQoKI2luIGRhdGEgZnJhbWVzCnBob3NwaG9wcm90ZWluX2RhdGEgPC0gZGF0YS5mcmFtZShwaG9zcGhvcHJvdGVpbl9kYXRhKSAjIDg4CnBwaW5kZXhfZGF0YSA8LSBkYXRhLmZyYW1lKHBwaW5kZXhfZGF0YSkgIyA4NQpwcm90X3F1YW50X2RhdGEgPC0gZGF0YS5mcmFtZShwcm90X3F1YW50X2RhdGEpICMgOTIKcm5hX2RhdGEgPC0gZGF0YS5mcmFtZShybmFfZGF0YSkgIyA3Nwprc2VhX2RhdGEgPC0gZGF0YS5mcmFtZShrc2VhX2RhdGEpICMgODUKCgojcGF0aWVudCBpbmZvCnBhdGllbnRzX2xpc3QgPC0gcmVhZF9leGNlbCgicGF0aWVudF9saXN0Lnhsc3giLCBzaGVldCA9ICJTaGVldDEiKQpwYXRpZW50c19saXN0IDwtIGRhdGEuZnJhbWUocGF0aWVudHNfbGlzdCkKcHRfaW5mbyA8LSByZWFkX2V4Y2VsKCJQb29yIHJpc2sgQU1MIGNsaW5pY2FsIGFuZCBnZW5vbWljIGRhdGEueGx0eCIpCgpgYGAKCgpDbGFyaWZ5IHBhdGllbnRzOiAKYGBge3J9CgoKIyBDbGFzc2lmeSBwYXRpZW50cyBpbnRvIHRoZSB0b3AgMjAgb2YgdGhlIHR3byBleHRyZW1lcywgdG9wIDIwIHdpdGggc2hvcnRlc3Qgc3Vydml2YWwgKGxlc3MgdGhhbiAwLjQzNiB5ZWFycykgYW5kIHRvcCAyMCBvZiB0aGUgbG9uZ2VzdCBzdXJ2aXZhbCAoaGlnaGVyIHRoYW4gMS44NTQgeWVhcnMpCgpzaG9ydF9zdXJ2aXZhbHMgPC0gcGF0aWVudHNfbGlzdCAlPiUKICBmaWx0ZXIoYFNVUlZJVkFMLi5ZUlMuYCA8IDAuNDM2KSAlPiUKICBhcnJhbmdlKGBTVVJWSVZBTC4uWVJTLmApICU+JQogIGhlYWQoMjApCgpsb25nX3N1cnZpdmFscyA8LSBwYXRpZW50c19saXN0ICU+JQogIGZpbHRlcihgU1VSVklWQUwuLllSUy5gID4gMS44NTQpICU+JQogIGFycmFuZ2UoZGVzYyhgU1VSVklWQUwuLllSUy5gKSkgJT4lCiAgaGVhZCgyMCkKCiMgRXh0cmFjdCB0aGUgc2FtcGxlIG5hbWVzCnNob3J0X3NhbXBsZXMgPC0gc2hvcnRfc3Vydml2YWxzJFNhbXBsZV9OYW1lCmxvbmdfc2FtcGxlcyA8LSBsb25nX3N1cnZpdmFscyRTYW1wbGVfTmFtZQoKYGBgCgoKUEhPU1BIT1BST1RFSU5TCgpgYGB7cn0KCiMgRmlsdGVyIHRoZSBwaG9zcGhvcHJvdGVpbiBkYXRhCnBob3NwaG9wcm90ZWluc19maWx0ZXJlZCA8LSBwaG9zcGhvcHJvdGVpbl9kYXRhICU+JQogIGRwbHlyOjpzZWxlY3QocGhvc3Bob3Byb3RlaW4sIG4ucGhvc3Bob3BlcHRpZGVzLCBzaXRlcywgYWxsX29mKHNob3J0X3NhbXBsZXMpLCBhbGxfb2YobG9uZ19zYW1wbGVzKSkKCmRpbShwaG9zcGhvcHJvdGVpbnNfZmlsdGVyZWQpCgpgYGAKClByZS1wcm9jZXNzaW5nIHN0ZXBzOgoKYGBge3J9CiMgQm94cGxvdCBiZWZvcmUgcHJlcHJvY2Vzc2luZwpib3hwbG90KHBob3NwaG9wcm90ZWluc19maWx0ZXJlZFssIC1jKDE6MyldLCBsYXMgPSAzLCBtYWluID0gIlBob3NwaG9wcm90ZWluIERhdGEgRGlzdHJpYnV0aW9uIEJlZm9yZSBQcmVwcm9jZXNzaW5nIiwgY2V4Lm1haW4gPSAyKSAgIyB0byBpbmNyZWFzZSB0aXRsZSB0ZXh0IHNpemUKCiNmaWx0ZXJpbmcgbG93IGNvdW50cyAKa2VlcF9waG9zcGhvIDwtIHJvd1N1bXMocGhvc3Bob3Byb3RlaW5zX2ZpbHRlcmVkWywgLWMoMTozKV0gPj0gMTApID49IDMKcGhvc3Bob3Byb3RlaW5zX2ZpbHRlcmVkIDwtIHBob3NwaG9wcm90ZWluc19maWx0ZXJlZFtrZWVwX3Bob3NwaG8sXQoKIyBMb2cyIHRyYW5zZm9ybWF0aW9uCmxvZzJfdHJhbnNmb3JtZWQgPC0gcGhvc3Bob3Byb3RlaW5zX2ZpbHRlcmVkCmxvZzJfdHJhbnNmb3JtZWRbLCAtYygxOjMpXSA8LSBsb2cyKHBob3NwaG9wcm90ZWluc19maWx0ZXJlZFssIC1jKDE6MyldICsgMSkKCiMgUXVhbnRpbGUgbm9ybWFsaXphdGlvbgpxdWFudGlsZV9ub3JtYWxpemVkIDwtIGxvZzJfdHJhbnNmb3JtZWQKcXVhbnRpbGVfbm9ybWFsaXplZFssIC1jKDE6MyldIDwtIG5vcm1hbGl6ZS5xdWFudGlsZXMoYXMubWF0cml4KGxvZzJfdHJhbnNmb3JtZWRbLCAtYygxOjMpXSkpCgojIFNjYWxpbmcgKGNlbnRlcmluZyBhbmQgc2NhbGluZykKc2NhbGVkIDwtIHF1YW50aWxlX25vcm1hbGl6ZWQKc2NhbGVkWywgLWMoMTozKV0gPC0gc2NhbGUocXVhbnRpbGVfbm9ybWFsaXplZFssIC1jKDE6MyldLCBjZW50ZXIgPSBUUlVFLCBzY2FsZSA9IFRSVUUpCgojIENyZWF0ZSB0aGUgZmluYWwgcHJlcHJvY2Vzc2VkIGRhdGFzZXQKcGhvc3Bob19maW5hbCA8LSBzY2FsZWQKCiMgQm94cGxvdCBhZnRlciBwcmVwcm9jZXNzaW5nCmJveHBsb3QocGhvc3Bob19maW5hbFssIC1jKDE6MyldLCBsYXMgPSAzLCBtYWluID0gIlBob3NwaG9wcm90ZWluIERhdGEgRGlzdHJpYnV0aW9uIEFmdGVyIFByZXByb2Nlc3NpbmcgKExvZzIsIFF1YW50aWxlIE5vcm1hbGl6YXRpb24sIFNjYWxpbmcpIiwgY2V4Lm1haW4gPSAyKSAKCgpgYGAKCgpEaWZmZXJlbnRpYWwgZXhwcmVzc2lvbiBhbmFseXNpcyB1c2luZyBsaW1tYTogCnVzZSBjb21wYXJlLmJ5LmxpbW1hIGZ1bmN0aW9uIC0gdGhlIHNhbWUgdXNlZCBpbiBhbGw6IApgYGB7cn0KCmNvbXBhcmUuYnkubGltbWEgPC0gZnVuY3Rpb24oZGYudG8uY29tcGFyZSwgY29udHJvbC5zYW1wbGVzLCB0ZXN0LnNhbXBsZXMpewogICMgTG9hZCBsaWJyYXJ5CiAgbGlicmFyeShsaW1tYSkKICAKICAjIERlZmluZSB0aGUgY29sdW1ucyBmb3IgY29udHJvbCBhbmQgdGVzdCBzYW1wbGVzCiAgY29udHJvbC5zYW1wbGVzIDwtIGludGVyc2VjdChjb250cm9sLnNhbXBsZXMsIGNvbG5hbWVzKGRmLnRvLmNvbXBhcmUpKQogIHRlc3Quc2FtcGxlcyA8LSBpbnRlcnNlY3QodGVzdC5zYW1wbGVzLCBjb2xuYW1lcyhkZi50by5jb21wYXJlKSkKICAKICAjIFN1YnNldCB0aGUgZGF0YWZyYW1lIHRvIGluY2x1ZGUgb25seSB0aGUgY29udHJvbCBhbmQgdGVzdCBzYW1wbGVzCiAgZGYucyA8LSBkZi50by5jb21wYXJlWywgYyhjb250cm9sLnNhbXBsZXMsIHRlc3Quc2FtcGxlcyldCiAgCiAgIyBDcmVhdGUgb3V0Y29tZSBsYWJlbHMgZm9yIHRoZSBzYW1wbGVzCiAgZGYuczEgPC0gZGF0YS5mcmFtZShvdXRjb21lID0gcmVwKCJjb250cm9sIiwgbGVuZ3RoKGNvbnRyb2wuc2FtcGxlcykpKQogIGRmLnMyIDwtIGRhdGEuZnJhbWUob3V0Y29tZSA9IHJlcCgidGVzdCIsIGxlbmd0aCh0ZXN0LnNhbXBsZXMpKSkKICBkZi5zcyA8LSByYmluZChkZi5zMSwgZGYuczIpCiAgCiAgIyBDcmVhdGUgdGhlIGRlc2lnbiBtYXRyaXggZm9yIGxpbW1hCiAgZGVzIDwtIGZhY3RvcihpZmVsc2UoZGYuc3Mkb3V0Y29tZSA9PSAidGVzdCIsICIxIiwgIjIiKSkKICBmYWNuYSA8LSBhZGROQShkZXMpCiAgZGVzaWduIDwtIG1vZGVsLm1hdHJpeCh+IDAgKyBmYWN0b3IoYyhmYWNuYSkpKQogIGNvbG5hbWVzKGRlc2lnbikgPC0gYygiY29udHJvbCIsICJ0ZXN0IikKICAKICAjIERlZmluZSB0aGUgY29udHJhc3QgbWF0cml4CiAgY29udHJhc3QubWF0cml4IDwtIG1ha2VDb250cmFzdHModGVzdCAtIGNvbnRyb2wsIGxldmVscyA9IGRlc2lnbikKICAKICAjIEZpdCB0aGUgbGluZWFyIG1vZGVsCiAgZml0IDwtIGxtRml0KGRmLnMsIGRlc2lnbikKICBmaXQyIDwtIGNvbnRyYXN0cy5maXQoZml0LCBjb250cmFzdC5tYXRyaXgpCiAgZml0MiA8LSBlQmF5ZXMoZml0MikKICAKICAjIEV4dHJhY3QgcC12YWx1ZXMgYW5kIGNvZWZmaWNpZW50cwogIHB2YWxzIDwtIGRhdGEuZnJhbWUoZml0MiRwLnZhbHVlKQogIGZ2YWxzIDwtIGRhdGEuZnJhbWUoZml0MiRjb2VmZmljaWVudHMpCiAgCiAgIyBDcmVhdGUgdGhlIHJlc3VsdCBkYXRhZnJhbWUgd2l0aCBkeW5hbWljIGNvbHVtbiBuYW1lcwogIGRmLnh4IDwtIGRhdGEuZnJhbWUocHJvdGVpbiA9IGRmLnRvLmNvbXBhcmVbLDFdLAogICAgICAgICAgICAgICAgICAgICAgZGlmZmVyZW5jZV90ZXN0X3ZzX2NvbnRyb2wgPSBmdmFscywKICAgICAgICAgICAgICAgICAgICAgIHB2YWx1ZXMgPSBwdmFscykKICBjb2xuYW1lcyhkZi54eCkgPC0gYyggIlgiLCAiZGlmZmVyZW5jZS5sb25nLnZzLnNob3J0IiwgInB2YWx1ZXMiKSAjdGhlIGZpcnN0IGNvbHVtbiBpcyBuYW1lZCBYLCBiZWNhdXNlIG9mIHRoZSBkaWZmZXJlbnQgZGF0YXNldHMgYW5kIGRpZmZlcmVudCBuYW1lcywgbmVlZGVkIGEgY29tbW9uIG5hbWUgZm9yIGFuYWx5c2lzCiAgCiAgIyBBZGp1c3QgcC12YWx1ZXMgLSBGRFIKICBkZi54eCRGRFIgPC0gcC5hZGp1c3QoZGYueHgkcHZhbHVlcywgbWV0aG9kID0gImZkciIpCiAgCiAgcmV0dXJuKGRmLnh4KQp9Cgojbm90ZTogdGhlIHBvc2l0aXZlOm1vc3QgZXhwcmVzc2VkIGluIHRoZSBzaG9ydCBzdXJ2aXZhbCAKYGBgCgoKCmBgYHtyfQoKIyBQZXJmb3JtIGRpZmZlcmVudGlhbCBleHByZXNzaW9uIGFuYWx5c2lzCmRmLmxpbW1hLnBob3NwaG8gPC0gY29tcGFyZS5ieS5saW1tYShwaG9zcGhvX2ZpbmFsLCBsb25nX3NhbXBsZXMsIHNob3J0X3NhbXBsZXMpCgoKIyBEZWZpbmUgdGhlIHAtdmFsdWUgdGhyZXNob2xkIGZvciBzaWduaWZpY2FuY2UKcF92YWx1ZV90aHJlc2hvbGQgPC0gMC4wNQoKIyBGaWx0ZXIgc2lnbmlmaWNhbnQgcmVzdWx0cyBiYXNlZCBvbiB0aGUgcC12YWx1ZQpzaWduaWZpY2FudF9waG9zcGhvX3Jlc3VsdHMgPC0gZGYubGltbWEucGhvc3Bob1tkZi5saW1tYS5waG9zcGhvJHB2YWx1ZXMgPCBwX3ZhbHVlX3RocmVzaG9sZCwgXQoKIyBWaWV3IGFsbCBzaWduaWZpY2FudCByZXN1bHRzCnByaW50KHNpZ25pZmljYW50X3Bob3NwaG9fcmVzdWx0cykKCgojIE9yZGVyIHRoZSBzaWduaWZpY2FudCByZXN1bHRzIGJ5IGFic29sdXRlIGRpZmZlcmVudGlhbCBleHByZXNzaW9uIC8gbW9zdCBleHByZXNzZWQgYnV0IGFsc28gcC12YWx1ZSA8MC4wNSAKc2lnbmlmaWNhbnRfcGhfcmVzIDwtIHNpZ25pZmljYW50X3Bob3NwaG9fcmVzdWx0c1tvcmRlcihhYnMoc2lnbmlmaWNhbnRfcGhvc3Bob19yZXN1bHRzJGRpZmZlcmVuY2UubG9uZy52cy5zaG9ydCksIGRlY3JlYXNpbmcgPSBUUlVFKSwgXQoKIyBGaWx0ZXIgdGhlIHRvcCAxMCBtb3N0IHNpZ25pZmljYW50IGhpdHMKdG9wX3NpZ25pZmljYW50X3BoIDwtIGhlYWQoc2lnbmlmaWNhbnRfcGhfcmVzLCAxMCkgCgojIFZpZXcgdGhlIHRvcCAxMApwcmludCh0b3Bfc2lnbmlmaWNhbnRfcGgpCgoKCmBgYAoKCgpgYGB7cn0KI3ZvbGNhbm8gcGxvdCAKCiMgRGVmaW5lIHAtdmFsdWUgLyB0aHJlc2hvbGQgb2Ygc2lnbmlmaWNhbmNlIApwdmFsX3RocmVzaG9sZCA8LSAwLjA1Cgojdm9sY2FubyBwbG90CmdncGxvdChkZi5saW1tYS5waG9zcGhvLCBhZXMoeCA9IGRpZmZlcmVuY2UubG9uZy52cy5zaG9ydCwgeSA9IC1sb2cxMChwdmFsdWVzKSkpICsKICAgIGdlb21fcG9pbnQoYWVzKGNvbG9yID0gcHZhbHVlcyA8IHB2YWxfdGhyZXNob2xkKSkgKwogICAgdGhlbWVfbWluaW1hbCgpICsKICAgIGxhYnModGl0bGUgPSAiVm9sY2FubyBQbG90IGZvciBQaG9zcGhvcHJvdGVpbiBEYXRhIiwgCiAgICAgICAgIHggPSAiTG9nMiBGb2xkIENoYW5nZSIsIAogICAgICAgICB5ID0gIi1sb2cxMChwLXZhbHVlKSIpICsKICAgIGdlb21fdGV4dF9yZXBlbChkYXRhID0gdG9wX3NpZ25pZmljYW50X3BoLCAjYWRkIHRoZSB0b3AgMTAgbW9zdCBzaWduaWZpY2FudCBmZWF0dXJlcyAKICAgICAgICAgICAgICAgICAgICBhZXMobGFiZWwgPSBYKSwKICAgICAgICAgICAgICAgICAgICBzaXplID0gMywgCiAgICAgICAgICAgICAgICAgICAgbWF4Lm92ZXJsYXBzID0gSW5mKSArICAjIFVzZSBJbmYgdG8gYXZvaWQgZmlsdGVyaW5nIG91dCB0b3AgNQogICAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGMoInJlZCIsICJibHVlIiksIG5hbWUgPSAicHZhbHVlcyA8IDAuMDUiKSArCiAgICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAicmlnaHQiKQoKYGBgCgoKClBhdGh3YXkgZW5yaWNobWVudCBhbmFseXNpczoKCkdPIEVucmljaG1lbnQgCgoKYGBge3J9CiMgTG9hZCBuZWNlc3NhcnkgbGlicmFyaWVzCmxpYnJhcnkoY2x1c3RlclByb2ZpbGVyKQpsaWJyYXJ5KG9yZy5Icy5lZy5kYikgCgoKIyBFeHRyYWN0IHNpZ25pZmljYW50IHBob3NwaG9wcm90ZWlucwpzaWduaWZpY2FudF9waCA8LSBzaWduaWZpY2FudF9waG9zcGhvX3Jlc3VsdHMkWAoKIyBDb252ZXJ0IHRvIEVudHJleiBJRHMKcGhfZW50cmV6X2lkcyA8LSBiaXRyKHNpZ25pZmljYW50X3BoLCBmcm9tVHlwZT0iU1lNQk9MIiwgdG9UeXBlPSJFTlRSRVpJRCIsIE9yZ0RiPW9yZy5Icy5lZy5kYikKIzYuNjclIG9mIGlucHV0IGdlbmUgSURzIGFyZSBmYWlsIHRvIG1hcC4uLgoKCiMgUGVyZm9ybSBHTyBlbnJpY2htZW50IGFuYWx5c2lzCgojYmlvbG9naWNhbCBwcm9jZXNzZXMgCmdvX3BoX2VucmljaG1lbnQgPC0gZW5yaWNoR08oZ2VuZSA9IHBoX2VudHJlel9pZHMkRU5UUkVaSUQsIAogICAgICAgICAgICAgICAgICAgICAgICAgIE9yZ0RiID0gb3JnLkhzLmVnLmRiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICBvbnQgPSAiQlAiLCAjICJCUCIgZm9yIEJpb2xvZ2ljYWwgUHJvY2Vzc2VzCiAgICAgICAgICAgICAgICAgICAgICAgICAgcEFkanVzdE1ldGhvZCA9ICJub25lIiwgIyBFbnN1cmVzIHRoYXQgdW5hZGp1c3RlZCBwLXZhbHVlcyBhcmUgdXNlZAogICAgICAgICAgICAgICAgICAgICAgICAgIHB2YWx1ZUN1dG9mZiA9IDAuMDEsICNzdGluZ2VzdCBjdXR0b2ZmIHZhbHVlIAogICAgICAgICAgICAgICAgICAgICAgICAgIHF2YWx1ZUN1dG9mZiA9IDAuMiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgcmVhZGFibGUgPSBUUlVFKQoKCgojIG90aGVyIGNhdGVnb3JpZXMgKE1GLCBDQykKZ29fZW5yaWNobWVudF9waF9NRiA8LSBlbnJpY2hHTyhnZW5lID0gcGhfZW50cmV6X2lkcyRFTlRSRVpJRCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgT3JnRGIgPSBvcmcuSHMuZWcuZGIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9udCA9ICJNRiIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBBZGp1c3RNZXRob2QgPSAibm9uZSIsICMiTUYiIGZvciBNb2xlY3VsYXIgRnVuY3Rpb25zLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHB2YWx1ZUN1dG9mZiA9IDAuMDEsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHF2YWx1ZUN1dG9mZiA9IDAuMiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVhZGFibGUgPSBUUlVFKQoKZ29fZW5yaWNobWVudF9waF9DQyA8LSBlbnJpY2hHTyhnZW5lID0gcGhfZW50cmV6X2lkcyRFTlRSRVpJRCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgT3JnRGIgPSBvcmcuSHMuZWcuZGIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9udCA9ICJDQyIsICMiQ0MiIGZvciBDZWxsdWxhciBDb21wb25lbnRzCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcEFkanVzdE1ldGhvZCA9ICJub25lIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHZhbHVlQ3V0b2ZmID0gMC4wMSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcXZhbHVlQ3V0b2ZmID0gMC4yLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWFkYWJsZSA9IFRSVUUpCgoKCmBgYAoKCmBgYHtyfQojIFZpc3VhbGl6ZSBmb3IgR08gYmlvbG9naWNhbCBwcm9jZXNzZXMgcGF0aHdheXMgCmJhcnBsb3QoZ29fcGhfZW5yaWNobWVudCwgc2hvd0NhdGVnb3J5ID0gMTAsIHRpdGxlID0gIkdPIEJpb2xvZ2ljYWwgUHJvY2Vzc2VzIEVucmljaG1lbnQgb2YgUGhvc3Bob3Byb3RlaW4gZGF0YSIpCmRvdHBsb3QoZ29fcGhfZW5yaWNobWVudCwgc2hvd0NhdGVnb3J5ID0gMTAsIHRpdGxlID0gIkdPIEJpb2xvZ2ljYWwgUHJvY2Vzc2VzIEVucmljaG1lbnQgb2YgUGhvc3Bob3Byb3RlaW4gZGF0YSIpCgoKIyBVc2UgaGVhdHBsb3QgCmhlYXRwbG90KGdvX3BoX2VucmljaG1lbnQsIHNob3dDYXRlZ29yeSA9IDEwKQpgYGAKCmBgYHtyfQojbmV0d29yayBwbG90CmNuZXRwbG90KGdvX3BoX2VucmljaG1lbnQsIHNob3dDYXRlZ29yeSA9IDEwLCB0aXRsZSA9ICJHZW5lLUNvbmNlcHQgTmV0d29yayBmb3IgQmlvbG9naWNhbCBQcm9jZXNzZXMgb2YgUGhvc3Bob3Byb3RlaW4gZGF0YSIsIAogICAgICAgICBtYXgub3ZlcmxhcHMgPSAxMDAsIG5vZGVfbGFiZWxfc2l6ZSA9IDMsIGxhYmVsX2ZvbnRzaXplID0gOCkgKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCksIAogICAgICAgIGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCksIAogICAgICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE0LCBmYWNlID0gImJvbGQiKSkKCiNkZWNpZGVkIG9uIHRoZSBudW1iZXIgNyBmb3IgdGhlIGNhdGVnb3JpZXMsIGFzIG1vcmUgb3ZlcndoZWxtcyB0aGUgcGxvdCBhbmQgZGF0YSBwb2ludHMgd2VyZSB1bmxhYmVsZWQgCmBgYAoKCmBgYHtyfQojIFZpc3VhbGl6ZSB0aGUgb3RoZXIgY2F0ZWdvcmllczogTUYsIENDCgojbW9sZWN1bGFyIGZ1bmN0aW9ucyAKZG90cGxvdChnb19lbnJpY2htZW50X3BoX01GLCBzaG93Q2F0ZWdvcnkgPSAxMCwgdGl0bGUgPSAiR08gTW9sZWN1bGFyIEZ1bmN0aW9ucyBFbnJpY2htZW50IG9mIFBob3NwaG9wcm90ZWluIGRhdGEiKQoKI2NlbGx1bGFyIGNvbXBvbmVudG5zCmRvdHBsb3QoZ29fZW5yaWNobWVudF9waF9DQywgc2hvd0NhdGVnb3J5ID0gMTAsIHRpdGxlID0gIkdPIENlbGx1bGFyIENvbXBvbmVudHMgRW5yaWNobWVudCBvZiBQaG9zcGhvcHJvdGVpbiBkYXRhIikKCmBgYAoKCkZvciBzcGVjaWZpY2FsbHkgYmFkLXJlc3BvbmRlcnMvIHRhcmdldHMgYXNzb2NpYXRlZCB3aXRoIHNob3J0IHN1cnZpdmFsOgoKCmBgYHtyfQojc3Vic2V0IHRoZSBkYXRhLCBrZWVwIG9ubHkgdXByZWd1bGF0ZWQgZmVhdHVyZXMgaW4gc2hvcnQgc3Vydml2YWwgZ3JvdXAgCnN1YnNldF9waCA8LSBzdWJzZXQoc2lnbmlmaWNhbnRfcGhvc3Bob19yZXN1bHRzLCBkaWZmZXJlbmNlLmxvbmcudnMuc2hvcnQgPiAwKQpjbGVhbl9zdWJzZXRfcGggPC0gc3Vic2V0X3BoJFgKCiMgQ29udmVydCB0aGVzZSBraW5hc2UgbmFtZXMgdG8gRW50cmV6IElEcwplbl9pZHNfcGggPC0gYml0cihjbGVhbl9zdWJzZXRfcGgsIGZyb21UeXBlID0gIlNZTUJPTCIsIHRvVHlwZSA9ICJFTlRSRVpJRCIsIE9yZ0RiID0gb3JnLkhzLmVnLmRiKQoKCiNHTyBlbnJpY2htZW50IApnb19waF9wX2VucmljaG1lbnQgPC0gZW5yaWNoR08oZ2VuZSA9IGVuX2lkc19waCRFTlRSRVpJRCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgT3JnRGIgPSBvcmcuSHMuZWcuZGIsIAogICAgICAgICAgICAgICAgICAgICAgICAgIG9udCA9ICJCUCIsICMgIkJQIiBmb3IgQmlvbG9naWNhbCBQcm9jZXNzZXMKICAgICAgICAgICAgICAgICAgICAgICAgICBwQWRqdXN0TWV0aG9kID0gIkJIIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgcHZhbHVlQ3V0b2ZmID0gMC4wNSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgcXZhbHVlQ3V0b2ZmID0gMC4yLCAKICAgICAgICAgICAgICAgICAgICAgICAgICByZWFkYWJsZSA9IFRSVUUpCgoKI1Bsb3RzCmJhcnBsb3QoZ29fcGhfcF9lbnJpY2htZW50LCBzaG93Q2F0ZWdvcnkgPSAxMCwgdGl0bGUgPSAiR08gQmlvbG9naWNhbCBQcm9jZXNzZXMgZW5yaWNoZWQgaW4gc2hvcnQgc3Vydml2YWwgZ3JvdXAiKQpkb3RwbG90KGdvX3BoX3BfZW5yaWNobWVudCwgc2hvd0NhdGVnb3J5ID0gMTAsIHRpdGxlID0gIkdPIEJpb2xvZ2ljYWwgUHJvY2Vzc2VzIGVucmljaGVkIGluIHNob3J0IHN1cnZpdmFsIGdyb3VwIikKaGVhdHBsb3QoZ29fcGhfcF9lbnJpY2htZW50LCBzaG93Q2F0ZWdvcnkgPSAxMCkKCgojbmV0d29yayBwbG90IApjbmV0cGxvdChnb19waF9wX2VucmljaG1lbnQsIHNob3dDYXRlZ29yeSA9IDQsIHRpdGxlID0gIkdlbmUtQ29uY2VwdCBOZXR3b3JrIGZvciBCaW9sb2dpY2FsIFByb2Nlc3NlcyBlbnJpY2hlZCBpbiBzaG9ydCBzdXJ2aXZhbCBncm91cCIsIAogICAgICAgICBtYXgub3ZlcmxhcHMgPSAxMDAsIG5vZGVfbGFiZWxfc2l6ZSA9IDMsIGxhYmVsX2ZvbnRzaXplID0gOCkgKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCksIAogICAgICAgIGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCksIAogICAgICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE0LCBmYWNlID0gImJvbGQiKSkKCiNkZWNpZGVkIG9uIDQgdG8gbm90IG92ZXJ3aGVsbSB0aGUgbmV0d29yayBwbG90IApgYGAKCgoKVXNpbmcgZ3Byb2ZpbGVyMi8gZm9yIGFsbCBzaWduaWZpY2FudCBkaWZmZXJlbnRpYWxseSBleHByZXNzc2VkIGZlYXR1cmVzOiAKCgpgYGB7cn0KCiMgUnVuIGdQcm9maWxlciBlbnJpY2htZW50IGFuYWx5c2lzCmdvc3RyZXNfcGggPC0gZ29zdChxdWVyeSA9IHBoX2VudHJlel9pZHMkRU5UUkVaSUQsIAogICAgICAgICAgICAgICAgb3JnYW5pc20gPSAiaHNhcGllbnMiLCAKICAgICAgICAgICAgICAgIHNvdXJjZXMgPSBjKCJHTzpCUCIsICJHTzpNRiIsICJHTzpDQyIsICJLRUdHIiwgIlJFQUMiLCAiV1AiKSwgCiAgICAgICAgICAgICAgICBzaWduaWZpY2FudCA9IFRSVUUsIAogICAgICAgICAgICAgICAgY29ycmVjdGlvbl9tZXRob2QgPSAiZmRyIiwgIAogICAgICAgICAgICAgICAgdXNlcl90aHJlc2hvbGQgPSAwLjA1KQoKIyBWaWV3IHRoZSByZXN1bHRzCmhlYWQoZ29zdHJlc19waCRyZXN1bHQpCgojIFBsb3QgdGhlIHJlc3VsdHMKZ29zdHBsb3QoZ29zdHJlc19waCwgY2FwcGVkID0gVFJVRSwgaW50ZXJhY3RpdmUgPSBGQUxTRSkKCmBgYAoKCgpgYGB7cn0KI0VuaGFuY2UgZnVuY3Rpb24gdG8gcGxvdCByZXN1bHRzIGZvciBhIHNwZWNpZmljIGNhdGVnb3J5IChHTywgS0VHRywgUkVBQ1RPTUUsIFdJS0lQQVRIV0FZUykgKyBhZGQgY29sb3JzCnBsb3RfcmVzdWx0cyA8LSBmdW5jdGlvbihyZXN1bHRzLCBjYXRlZ29yeSwgdGl0bGUpIHsKICBmaWx0ZXJlZF9yZXN1bHRzIDwtIHJlc3VsdHMgJT4lIAogICAgZmlsdGVyKHNvdXJjZSA9PSBjYXRlZ29yeSkgJT4lIAogICAgYXJyYW5nZShwX3ZhbHVlKSAlPiUgCiAgICBoZWFkKDEwKSAgIyBUb3AgMTAgcmVzdWx0cwogIAogIGdncGxvdChmaWx0ZXJlZF9yZXN1bHRzLCBhZXMoeCA9IHJlb3JkZXIodGVybV9uYW1lLCAtcF92YWx1ZSksIHkgPSAtbG9nMTAocF92YWx1ZSksIGZpbGwgPSAtbG9nMTAocF92YWx1ZSkpKSArCiAgICBnZW9tX2NvbCgpICsKICAgIGNvb3JkX2ZsaXAoKSArCiAgICBzY2FsZV9maWxsX2dyYWRpZW50KGxvdyA9ICJsaWdodGJsdWUiLCBoaWdoID0gImRhcmtibHVlIikgKyAgIyBHcmFkaWVudCBjb2xvciBmaWxsCiAgICBsYWJzKHRpdGxlID0gdGl0bGUsIHggPSAiUGF0aHdheSIsIHkgPSAiLWxvZzEwKHAtdmFsdWUpIikgKwogICAgdGhlbWVfbWluaW1hbCgpICsKICAgIHRoZW1lKAogICAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNiwgZmFjZSA9ICJib2xkIiksIAogICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIpLCAKICAgICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyKSwKICAgICAgbGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiCiAgICApCn0KCiMgUGxvdCBmb3IgZWFjaCBjYXRlcm9neSAKYnBfcGxvdF9waCA8LSBwbG90X3Jlc3VsdHMoZ29zdHJlc19waCRyZXN1bHQsICJHTzpCUCIsICJUb3AgQmlvbG9naWNhbCBQcm9jZXNzZXMgb2YgUGhvc3Bob3Byb3RlaW4gZGF0YSIpCm1mX3Bsb3RfcGggPC0gcGxvdF9yZXN1bHRzKGdvc3RyZXNfcGgkcmVzdWx0LCAiR086TUYiLCAiVG9wIE1vbGVjdWxhciBGdW5jdGlvbnMgb2YgUGhvc3Bob3Byb3RlaW4gZGF0YSIpCmNjX3Bsb3RfcGggPC0gcGxvdF9yZXN1bHRzKGdvc3RyZXNfcGgkcmVzdWx0LCAiR086Q0MiLCAiVG9wIENlbGx1bGFyIENvbXBvbmVudHMgb2YgUGhvc3Bob3Byb3RlaW4gZGF0YSIpCnJlYWNfcGxvdF9waCA8LSBwbG90X3Jlc3VsdHMoZ29zdHJlc19waCRyZXN1bHQsICJSRUFDIiwgIlRvcCBSZWFjdG9tZSBQYXRod2F5cyBvZiBQaG9zcGhvcHJvdGVpbiBkYXRhIikKa2VnZ19wbG90X3BoIDwtIHBsb3RfcmVzdWx0cyhnb3N0cmVzX3BoJHJlc3VsdCwgIktFR0ciLCAiVG9wIEtFR0cgUGF0aHdheXMgb2YgUGhvc3Bob3Byb3RlaW4gZGF0YSIpCndwX3Bsb3RfcGggPC0gcGxvdF9yZXN1bHRzKGdvc3RyZXNfcGgkcmVzdWx0LCAiV1AiLCAiVG9wIFdpa2lQYXRod2F5cyBvZiBQaG9zcGhvcHJvdGVpbiBkYXRhIikKCiMgUHJpbnQgdGhlIHBsb3RzCnByaW50KGJwX3Bsb3RfcGgpCnByaW50KG1mX3Bsb3RfcGgpCnByaW50KGNjX3Bsb3RfcGgpCnByaW50KHJlYWNfcGxvdF9waCkgI05vIFJlYWN0b21lIHBhdGh3YXlzIGlkZW50aWZpZWQKcHJpbnQoa2VnZ19wbG90X3BoKSAjTm8gS0VHRyBwYXRoYXlzIGlkZW50aWZpZWQKcHJpbnQod3BfcGxvdF9waCkgI05PIFdpa2kgUGF0aHdheXMgaWRlbnRpZmllZAoKYGBgCgoKUFBfSU5ERVggZGF0YToKCgpgYGB7cn0KIyBGaWx0ZXIgcHBpbmRleCBkYXRhCnBwaW5kZXhfZmlsdGVyZWQgPC0gcHBpbmRleF9kYXRhICU+JQogIGRwbHlyOjpzZWxlY3QoWCwgYWxsX29mKHNob3J0X3NhbXBsZXMpLCBhbGxfb2YobG9uZ19zYW1wbGVzKSkKCmRpbShwcGluZGV4X2ZpbHRlcmVkKQpgYGAKClByZS1wcm9jZXNzaW5nIHN0ZXBzOiAKCmBgYHtyfQojIEJveHBsb3QgYmVmb3JlIHByZXByb2Nlc3NpbmcKYm94cGxvdChwcGluZGV4X2ZpbHRlcmVkWywgLTFdLCBsYXMgPSAzLCBtYWluID0gInBwSW5kZXggRGF0YSBEaXN0cmlidXRpb24gQmVmb3JlIFByZXByb2Nlc3NpbmciLCBjZXgubWFpbiA9IDIpICAjIHRvIGluY3JlYXNlIHRpdGxlIHRleHQgc2l6ZQoKIyBGaWx0ZXIgb3V0IGxvdyBjb3VudHMKa2VlcF9wcGluZGV4IDwtIHJvd1N1bXMocHBpbmRleF9maWx0ZXJlZFssIC0xXSA+PSAxMCkgPj0gMwpwcGluZGV4X2ZpbHRlcmVkIDwtIHBwaW5kZXhfZmlsdGVyZWRba2VlcF9wcGluZGV4LF0KCiMgTG9nMiB0cmFuc2Zvcm1hdGlvbgpsb2cyX3RyYW5zZm9ybWVkIDwtIHBwaW5kZXhfZmlsdGVyZWQKbG9nMl90cmFuc2Zvcm1lZFssIC0xXSA8LSBsb2cyKHBwaW5kZXhfZmlsdGVyZWRbLCAtMV0gKyAxKQoKIyBRdWFudGlsZSBub3JtYWxpemF0aW9uCnF1YW50aWxlX25vcm1hbGl6ZWQgPC0gbG9nMl90cmFuc2Zvcm1lZApxdWFudGlsZV9ub3JtYWxpemVkWywgLTFdIDwtIG5vcm1hbGl6ZS5xdWFudGlsZXMoYXMubWF0cml4KGxvZzJfdHJhbnNmb3JtZWRbLCAtMV0pKQoKIyBTY2FsaW5nIChjZW50ZXJpbmcgYW5kIHNjYWxpbmcpCnNjYWxlZCA8LSBxdWFudGlsZV9ub3JtYWxpemVkCnNjYWxlZFssIC0xXSA8LSBzY2FsZShxdWFudGlsZV9ub3JtYWxpemVkWywgLTFdLCBjZW50ZXIgPSBUUlVFLCBzY2FsZSA9IFRSVUUpCgojIGZpbmFsIHByZXByb2Nlc3NlZCBkYXRhc2V0CnBwaW5kZXhfZmluYWwgPC0gc2NhbGVkCgojIEJveHBsb3QgYWZ0ZXIgcHJlcHJvY2Vzc2luZwpib3hwbG90KHBwaW5kZXhfZmluYWxbLCAtMV0sIGxhcyA9IDMsIG1haW4gPSAicHBJbmRleCBEYXRhIERpc3RyaWJ1dGlvbiBBZnRlciBQcmVwcm9jZXNzaW5nIChMb2cyLCBRdWFudGlsZSBOb3JtYWxpemF0aW9uLCBTY2FsaW5nKSIsIGNleC5tYWluID0gMikgIAoKYGBgCgoKCkRpZmZlcmVudGlhbCBleHJlc3Npb24gYW5hbHlzaXMgLSBsaW1tYToKCmBgYHtyfQoKIyBQZXJmb3JtIGRpZmZlcmVudGlhbCBhbmFseXNpcwpkZi5saW1tYS5wcCA8LSBjb21wYXJlLmJ5LmxpbW1hKHBwaW5kZXhfZmluYWwsIGxvbmdfc2FtcGxlcywgc2hvcnRfc2FtcGxlcykKCgojIEZpbHRlciBzaWduaWZpY2FudCByZXN1bHRzIGJhc2VkIG9uIHAtdmFsdWUKc2lnbmlmaWNhbnRfcHBfcmVzdWx0cyA8LSBkZi5saW1tYS5wcFtkZi5saW1tYS5wcCRwdmFsdWVzIDwgcF92YWx1ZV90aHJlc2hvbGQsIF0KCiNwcmludCB0aGUgc2lnbmlmaWNhbnQgcmVzdWx0cwpwcmludChzaWduaWZpY2FudF9wcF9yZXN1bHRzKQoKCiMgT3JkZXIgdGhlIHNpZ25pZmljYW50IHJlc3VsdHMgYnkgYWJzb2x1dGUgZGlmZmVyZW50aWFsIGV4cHJlc3Npb24gLyBtb3N0IGV4cHJlc3NlZCBidXQgYWxzbyBwdmFsdWUgPDAuMDUgCnNpZ25pZmljYW50X3BwX3JlcyA8LSBzaWduaWZpY2FudF9wcF9yZXN1bHRzW29yZGVyKGFicyhzaWduaWZpY2FudF9wcF9yZXN1bHRzJGRpZmZlcmVuY2UubG9uZy52cy5zaG9ydCksIGRlY3JlYXNpbmcgPSBUUlVFKSwgXQoKCiMgVmlldyB0aGUgdG9wIDEwIG1vc3Qgc2lnbmlmaWNhbnQgaGl0cwp0b3Bfc2lnbmlmaWNhbnRfcHAgPC0gaGVhZChzaWduaWZpY2FudF9wcF9yZXMsIDEwKSAgCiNwcmludCB0b3AgMTAgCnByaW50KHRvcF9zaWduaWZpY2FudF9wcCkKCgpgYGAKCgpgYGB7cn0KCiMgdm9sY2FubyBwbG90IGZvciB0aGUgZGlmZmVyZW50aWFsIGV4cHJlc3Npb24gcmVzdWx0cwoKZ2dwbG90KGRmLmxpbW1hLnBwLCBhZXMoeCA9IGRpZmZlcmVuY2UubG9uZy52cy5zaG9ydCwgeSA9IC1sb2cxMChwdmFsdWVzKSkpICsKICAgIGdlb21fcG9pbnQoYWVzKGNvbG9yID0gcHZhbHVlcyA8IHB2YWxfdGhyZXNob2xkKSkgKwogICAgdGhlbWVfbWluaW1hbCgpICsKICAgIGxhYnModGl0bGUgPSAiVm9sY2FubyBQbG90IGZvciBQUC1pbmRleCBEYXRhIiwgCiAgICAgICAgIHggPSAiTG9nMiBGb2xkIENoYW5nZSIsIAogICAgICAgICB5ID0gIi1sb2cxMChwLXZhbHVlKSIpICsKICAgIGdlb21fdGV4dF9yZXBlbChkYXRhID0gdG9wX3NpZ25pZmljYW50X3BwLCAjYWRkIGluIHRleHQgdGhlIHRvcCAxMCByZXN1bHRzIAogICAgICAgICAgICAgICAgICAgIGFlcyhsYWJlbCA9IFgpLAogICAgICAgICAgICAgICAgICAgIHNpemUgPSAzLCAKICAgICAgICAgICAgICAgICAgICBtYXgub3ZlcmxhcHMgPSBJbmYpICsgICMgVXNlIEluZiB0byBhdm9pZCBmaWx0ZXJpbmcgb3V0IHRvcCA1CiAgICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gYygicmVkIiwgImJsdWUiKSwgbmFtZSA9ICJwdmFsdWVzIDwgMC4wNSIpICsKICAgIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJyaWdodCIpCmBgYAoKClBhdGh3YXkgZW5yaWNobWVudCBhbmFseXNpczoKCkdPIEVucmljaG1lbnQgCgoKYGBge3J9CgojIEV4dHJhY3QgdGhlIHN5bWJvbHMgCnNpZ25pZmljYW50X3BwIDwtIHVuaXF1ZShzYXBwbHkoc3Ryc3BsaXQoc2lnbmlmaWNhbnRfcHBfcmVzdWx0cyRYLCAiXFwoIiksIGBbYCwgMSkpCgojIENvbnZlcnQgdG8gRW50cmV6IElEcwplbnRyZXpfaWRzX3BwIDwtIGJpdHIoc2lnbmlmaWNhbnRfcHAsIGZyb21UeXBlID0gIlNZTUJPTCIsIHRvVHlwZSA9ICJFTlRSRVpJRCIsIE9yZ0RiID0gb3JnLkhzLmVnLmRiKQojIzguMTYlIG9mIGlucHV0IGdlbmUgSURzIGFyZSBmYWlsIHRvIG1hcC4uLgoKCiMgUGVyZm9ybSBHTyBlbnJpY2htZW50IGFuYWx5c2lzCmdvX3BwX2VucmljaG1lbnQgPC0gZW5yaWNoR08oZ2VuZSA9IGVudHJlel9pZHNfcHAkRU5UUkVaSUQsIAogICAgICAgICAgICAgICAgICAgICAgICAgIE9yZ0RiID0gb3JnLkhzLmVnLmRiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICBvbnQgPSAiQlAiLCAjICJCUCIgZm9yIEJpb2xvZ2ljYWwgUHJvY2Vzc2VzCiAgICAgICAgICAgICAgICAgICAgICAgICAgcEFkanVzdE1ldGhvZCA9ICJCSCIsIAogICAgICAgICAgICAgICAgICAgICAgICAgIHB2YWx1ZUN1dG9mZiA9IDAuMDUsIAogICAgICAgICAgICAgICAgICAgICAgICAgIHF2YWx1ZUN1dG9mZiA9IDAuMiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgcmVhZGFibGUgPSBUUlVFKQoKCiMgb3RoZXIgY2F0ZWdvcmllcyAoTUYsIENDKQpnb19lbnJpY2htZW50X3BwX01GIDwtIGVucmljaEdPKGdlbmUgPSBlbnRyZXpfaWRzX3BwJEVOVFJFWklELCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBPcmdEYiA9IG9yZy5Icy5lZy5kYiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb250ID0gIk1GIiwgIyJNRiIgZm9yIE1vbGVjdWxhciBGdW5jdGlvbnMKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwQWRqdXN0TWV0aG9kID0gIkJIIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHZhbHVlQ3V0b2ZmID0gMC4wNSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcXZhbHVlQ3V0b2ZmID0gMC4yLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWFkYWJsZSA9IFRSVUUpCgpnb19lbnJpY2htZW50X3BwX0NDIDwtIGVucmljaEdPKGdlbmUgPSBlbnRyZXpfaWRzX3BwJEVOVFJFWklELCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBPcmdEYiA9IG9yZy5Icy5lZy5kYiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb250ID0gIkNDIiwgIyJDQyIgZm9yIENlbGx1bGFyIENvbXBvbmVudHMKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwQWRqdXN0TWV0aG9kID0gIkJIIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHZhbHVlQ3V0b2ZmID0gMC4wNSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcXZhbHVlQ3V0b2ZmID0gMC4yLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWFkYWJsZSA9IFRSVUUpCgoKCmBgYAoKCgpgYGB7cn0KCiMgVmlzdWFsaXplIGZvciBHTyBiaW9sb2dpY2FsIHByb2Nlc3NlcyBwYXRod2F5cyAKYmFycGxvdChnb19wcF9lbnJpY2htZW50LCBzaG93Q2F0ZWdvcnkgPSAxMCwgdGl0bGUgPSAiR08gQmlvbG9naWNhbCBQcm9jZXNzZXMgRW5yaWNobWVudCIpCmRvdHBsb3QoZ29fcHBfZW5yaWNobWVudCwgc2hvd0NhdGVnb3J5ID0gMTAsIHRpdGxlID0gIkdPIEJpb2xvZ2ljYWwgUHJvY2Vzc2VzIEVucmljaG1lbnQiKQoKIyBVc2UgaGVhdHBsb3QgCmhlYXRwbG90KGdvX3BwX2VucmljaG1lbnQsIHNob3dDYXRlZ29yeSA9IDEwKQoKYGBgCgpgYGB7cn0KI25ldHdvcmsgcGxvdApjbmV0cGxvdChnb19wcF9lbnJpY2htZW50LCBzaG93Q2F0ZWdvcnkgPSA0LCB0aXRsZSA9ICJHZW5lLUNvbmNlcHQgTmV0d29yayBmb3IgQmlvbG9naWNhbCBQcm9jZXNzZXMiLCAKICAgICAgICAgbWF4Lm92ZXJsYXBzID0gMTAwLCBub2RlX2xhYmVsX3NpemUgPSAzLCBsYWJlbF9mb250c2l6ZSA9IDgpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTApLCAKICAgICAgICBheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTApLCAKICAgICAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCwgZmFjZSA9ICJib2xkIikpCgojZGVjaWRlZCBvbiB0aGUgbnVtYmVyIDQgZm9yIHRoZSBjYXRlZ29yaWVzLCBhcyBtb3JlIG92ZXJ3aGVsbXMgdGhlIHBsb3QgYW5kIGRhdGEgcG9pbnRzIHdlcmUgdW5sYWJlbGVkIApgYGAKCgpgYGB7cn0KIyBWaXN1YWxpemUgTUYsIENDCgojbW9sZWN1bGFyIGZ1bmN0aW9ucyAKZG90cGxvdChnb19lbnJpY2htZW50X3BwX01GLCBzaG93Q2F0ZWdvcnkgPSAxMCwgdGl0bGUgPSAiR08gTW9sZWN1bGFyIEZ1bmN0aW9ucyBFbnJpY2htZW50IikKCiNjZWxsdWxhciBjb21wb25lbnRzIApkb3RwbG90KGdvX2VucmljaG1lbnRfcHBfQ0MsIHNob3dDYXRlZ29yeSA9IDEwLCB0aXRsZSA9ICJHTyBDZWxsdWxhciBDb21wb25lbnRzIEVucmljaG1lbnQiKQoKYGBgCgpGb3Igc3BlY2lmaWNhbGx5IGJhZC1yZXNwb25kZXJzLyB0YXJnZXRzIGFzc29jaWF0ZWQgd2l0aCBzaG9ydCBzdXJ2aXZhbCBncm91cDoKCmBgYHtyfQoKI3N1YnNldCB0aGUgZGF0YSwga2VlcCBvbmx5IHVwcmVndWxhdGVkIGZlYXR1cmVzIGluIHNob3J0IHN1cnZpdmFsIGdyb3VwIApzdWJzZXRfcHAgPC0gc3Vic2V0KHNpZ25pZmljYW50X3BwX3Jlc3VsdHMsIGRpZmZlcmVuY2UubG9uZy52cy5zaG9ydCA+IDApCiNjbGVhbiB0aGUgZGF0YSAtIHJlYWR5IGZvciBHTyBwYXRod2F5IGVucmljaG1lbnQgCmNsZWFuX3N1YnNldF9wcCA8LSB1bmlxdWUoc2FwcGx5KHN0cnNwbGl0KHN1YnNldF9wcCRYLCAiXFwoIiksIGBbYCwgMSkpCgojIENvbnZlcnQgdGhlc2Uga2luYXNlIG5hbWVzIHRvIEVudHJleiBJRHMKZW5faWRzX3BwIDwtIGJpdHIoY2xlYW5fc3Vic2V0X3BwLCBmcm9tVHlwZSA9ICJTWU1CT0wiLCB0b1R5cGUgPSAiRU5UUkVaSUQiLCBPcmdEYiA9IG9yZy5Icy5lZy5kYikKCiNHTyBwYXRod2F5IGVucmljaG1lbnQgCmdvX3BwX3BfZW5yaWNobWVudCA8LSBlbnJpY2hHTyhnZW5lID0gZW5faWRzX3BwJEVOVFJFWklELCAKICAgICAgICAgICAgICAgICAgICAgICAgICBPcmdEYiA9IG9yZy5Icy5lZy5kYiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgb250ID0gIkJQIiwgIyAiQlAiIGZvciBCaW9sb2dpY2FsIFByb2Nlc3NlcwogICAgICAgICAgICAgICAgICAgICAgICAgIHBBZGp1c3RNZXRob2QgPSAiQkgiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICBwdmFsdWVDdXRvZmYgPSAwLjA1LCAKICAgICAgICAgICAgICAgICAgICAgICAgICBxdmFsdWVDdXRvZmYgPSAwLjIsIAogICAgICAgICAgICAgICAgICAgICAgICAgIHJlYWRhYmxlID0gVFJVRSkKCgojUGxvdHMKYmFycGxvdChnb19wcF9wX2VucmljaG1lbnQsIHNob3dDYXRlZ29yeSA9IDEwLCB0aXRsZSA9ICJHTyBCaW9sb2dpY2FsIFByb2Nlc3NlcyBlbnJpY2hlZCBpbiBzaG9ydCBzdXJ2aXZhbCBncm91cCIpCmRvdHBsb3QoZ29fcHBfcF9lbnJpY2htZW50LCBzaG93Q2F0ZWdvcnkgPSAxMCwgdGl0bGUgPSAiR08gQmlvbG9naWNhbCBQcm9jZXNzZXMgZW5yaWNoZWQgaW4gc2hvcnQgc3Vydml2YWwgZ3JvdXAiKQpoZWF0cGxvdChnb19wcF9wX2VucmljaG1lbnQsIHNob3dDYXRlZ29yeSA9IDEwKQoKCiNuZXR3b3JrIHBsb3QgCmNuZXRwbG90KGdvX3BwX3BfZW5yaWNobWVudCwgc2hvd0NhdGVnb3J5ID0gNCwgdGl0bGUgPSAiR2VuZS1Db25jZXB0IE5ldHdvcmsgZm9yIEJpb2xvZ2ljYWwgUHJvY2Vzc2VzIGVucmljaGVkIGluIHNob3J0IHN1cnZpdmFsIGdyb3VwIiwgCiAgICAgICAgIG1heC5vdmVybGFwcyA9IDEwMCwgbm9kZV9sYWJlbF9zaXplID0gMywgbGFiZWxfZm9udHNpemUgPSA4KSArCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwKSwgCiAgICAgICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwKSwgCiAgICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTQsIGZhY2UgPSAiYm9sZCIpKQojZGVjaWRlZCBvbiA0IHRvIG5vdCBvdmVyd2hlbG0gdGhlIG5ldHdvcmsgcGxvdAogCmBgYAoKClVzaW5nIGdwcm9maWxlcjIgLyB1c2luZyBhbGwgc2lnbmlmaWNhbnQgZGlmZmVyZW50aWFsbHkgZXhwcmVzc2VkIGZlYXR1cmVzOiAKCmBgYHtyfQoKI2dQcm9maWxlciBlbnJpY2htZW50IGFuYWx5c2lzCmdvc3RyZXNfcHAgPC0gZ29zdChxdWVyeSA9IGVudHJlel9pZHNfcHAkRU5UUkVaSUQsIAogICAgICAgICAgICAgICAgb3JnYW5pc20gPSAiaHNhcGllbnMiLCAKICAgICAgICAgICAgICAgIHNvdXJjZXMgPSBjKCJHTzpCUCIsICJHTzpNRiIsICJHTzpDQyIsICJLRUdHIiwgIlJFQUMiLCAiV1AiKSwgCiAgICAgICAgICAgICAgICBzaWduaWZpY2FudCA9IFRSVUUsIAogICAgICAgICAgICAgICAgY29ycmVjdGlvbl9tZXRob2QgPSAiZmRyIiwgIAogICAgICAgICAgICAgICAgdXNlcl90aHJlc2hvbGQgPSAwLjA1KQoKIyBWaWV3IHJlc3VsdHMKaGVhZChnb3N0cmVzX3BwJHJlc3VsdCkKCiMgUGxvdCByZXN1bHRzCmdvc3RwbG90KGdvc3RyZXNfcHAsIGNhcHBlZCA9IFRSVUUsIGludGVyYWN0aXZlID0gRkFMU0UpCmBgYAoKYGBge3J9CgojIFBsb3QgZm9yIGVhY2ggY2F0ZWdvcnkgKEdPLCBLRUdHLCBSRUFDVE9NRSwgV0lLSVBBVEhXQVlTKQpicF9wbG90X3BwIDwtIHBsb3RfcmVzdWx0cyhnb3N0cmVzX3BwJHJlc3VsdCwgIkdPOkJQIiwgIlRvcCBCaW9sb2dpY2FsIFByb2Nlc3NlcyIpCm1mX3Bsb3RfcHAgPC0gcGxvdF9yZXN1bHRzKGdvc3RyZXNfcHAkcmVzdWx0LCAiR086TUYiLCAiVG9wIE1vbGVjdWxhciBGdW5jdGlvbnMiKQpjY19wbG90X3BwIDwtIHBsb3RfcmVzdWx0cyhnb3N0cmVzX3BwJHJlc3VsdCwgIkdPOkNDIiwgIlRvcCBDZWxsdWxhciBDb21wb25lbnRzIikKcmVhY19wbG90X3BwIDwtIHBsb3RfcmVzdWx0cyhnb3N0cmVzX3BwJHJlc3VsdCwgIlJFQUMiLCAiVG9wIFJlYWN0b21lIFBhdGh3YXlzIikKa2VnZ19wbG90X3BwIDwtIHBsb3RfcmVzdWx0cyhnb3N0cmVzX3BwJHJlc3VsdCwgIktFR0ciLCAiVG9wIEtFR0cgUGF0aHdheXMiKQp3cF9wbG90X3BwIDwtIHBsb3RfcmVzdWx0cyhnb3N0cmVzX3BwJHJlc3VsdCwgIldQIiwgIlRvcCBXaWtpUGF0aHdheXMiKQoKIyBQcmludCBwbG90cwpwcmludChicF9wbG90X3BwKQpwcmludChtZl9wbG90X3BwKQpwcmludChjY19wbG90X3BwKQpwcmludChyZWFjX3Bsb3RfcHApCnByaW50KGtlZ2dfcGxvdF9wcCkgI05vIEtFR0cgcGF0aHdheXMgaWRlbnRpZmllZCAKcHJpbnQod3BfcGxvdF9wcCkgCgpgYGAKCgoKUFJPVEVJTiBRVUFOVElGSUNBVElPTgoKCmBgYHtyfQojIEZpbHRlciBwcm90ZWluIHF1YW50aWZpY2F0aW9uIGRhdGEKcHJvdF9xdWFudF9maWx0ZXJlZCA8LSBwcm90X3F1YW50X2RhdGEgJT4lCiAgZHBseXI6OnNlbGVjdChYLCBhbGxfb2Yoc2hvcnRfc2FtcGxlcyksIGFsbF9vZihsb25nX3NhbXBsZXMpKQoKZGltKHByb3RfcXVhbnRfZmlsdGVyZWQpCgpgYGAKCgpQcmUtcHJvY2Vzc2luZyBzdGVwczoKCmBgYHtyfQoKIyBCb3hwbG90IGJlZm9yZSBwcmVwcm9jZXNzaW5nCmJveHBsb3QocHJvdF9xdWFudF9maWx0ZXJlZFssIC0xXSwgbGFzID0gMywgbWFpbiA9ICJQcm90ZWluIHF1YW50aWZpY2F0aW9uIERhdGEgRGlzdHJpYnV0aW9uIEJlZm9yZSBQcmVwcm9jZXNzaW5nIiwgY2V4Lm1haW4gPSAyKQoKIyBmaWx0ZXJpbmcgb3V0IGxvdyBjb3VudHMKa2VlcF9wcm90X3F1YW50IDwtIHJvd1N1bXMocHJvdF9xdWFudF9maWx0ZXJlZFssIC0xXSA+PSAxMCkgPj0gMwpwcm90X3F1YW50X2ZpbHRlcmVkIDwtIHByb3RfcXVhbnRfZmlsdGVyZWRba2VlcF9wcm90X3F1YW50LF0KCiMgTG9nMiB0cmFuc2Zvcm1hdGlvbgpsb2cyX3RyYW5zZm9ybWVkIDwtIHByb3RfcXVhbnRfZmlsdGVyZWQKbG9nMl90cmFuc2Zvcm1lZFssIC0xXSA8LSBsb2cyKHByb3RfcXVhbnRfZmlsdGVyZWRbLCAtMV0gKyAxKQoKIyBRdWFudGlsZSBub3JtYWxpemF0aW9uCnF1YW50aWxlX25vcm1hbGl6ZWQgPC0gbG9nMl90cmFuc2Zvcm1lZApxdWFudGlsZV9ub3JtYWxpemVkWywgLTFdIDwtIG5vcm1hbGl6ZS5xdWFudGlsZXMoYXMubWF0cml4KGxvZzJfdHJhbnNmb3JtZWRbLCAtMV0pKQoKIyBTY2FsaW5nIChjZW50ZXJpbmcgYW5kIHNjYWxpbmcpCnNjYWxlZCA8LSBxdWFudGlsZV9ub3JtYWxpemVkCnNjYWxlZFssIC0xXSA8LSBzY2FsZShxdWFudGlsZV9ub3JtYWxpemVkWywgLTFdLCBjZW50ZXIgPSBUUlVFLCBzY2FsZSA9IFRSVUUpCgojIENyZWF0ZSB0aGUgZmluYWwgcHJlcHJvY2Vzc2VkIGRhdGFzZXQKcHJvdF9xdWFudF9maW5hbCA8LSBzY2FsZWQKCiMgQm94cGxvdCBhZnRlciBwcmVwcm9jZXNzaW5nCmJveHBsb3QocHJvdF9xdWFudF9maW5hbFssIC0xXSwgbGFzID0gMywgbWFpbiA9ICJQcm90ZWluIHF1YW50aWZpY2F0aW9uIERhdGEgRGlzdHJpYnV0aW9uIEFmdGVyIFByZXByb2Nlc3NpbmcgKExvZzIsIFF1YW50aWxlIE5vcm1hbGl6YXRpb24sIFNjYWxpbmcpIiwgY2V4Lm1haW4gPSAyKQoKCmBgYAoKCkRpZmZlcmVudGlhbCBleHByZXNzaW9uIGFuYWx5c2lzOiAKCmBgYHtyfQojIFBlcmZvcm0gZGlmZmVyZW50aWFsIGV4cHJlc3Npb24gYW5hbHlzaXMKZGYubGltbWEucXVhbnQgPC0gY29tcGFyZS5ieS5saW1tYShwcm90X3F1YW50X2ZpbmFsLCBsb25nX3NhbXBsZXMsIHNob3J0X3NhbXBsZXMpCgojIERlZmluZSB0aGUgcC12YWx1ZSB0aHJlc2hvbGQgZm9yIHNpZ25pZmljYW5jZQpwX3ZhbHVlX3RocmVzaG9sZCA8LSAwLjA1CgojIEZpbHRlciBzaWduaWZpY2FudCByZXN1bHRzIGJhc2VkIG9uIHAtdmFsdWUKc2lnbmlmaWNhbnRfcHFfcmVzdWx0cyA8LSBkZi5saW1tYS5xdWFudFtkZi5saW1tYS5xdWFudCRwdmFsdWVzIDwgcF92YWx1ZV90aHJlc2hvbGQsIF0KCiMgUHJpbnQgc2lnbmlmaWNhbnQgcmVzdWx0cwpwcmludChzaWduaWZpY2FudF9wcV9yZXN1bHRzKQoKIyBPcmRlciB0aGUgc2lnbmlmaWNhbnQgcmVzdWx0cyBieSBhYnNvbHV0ZSBkaWZmZXJlbnRpYWwgZXhwcmVzc2lvbiAvIG1vc3QgZXhwcmVzc2VkIGJ1dCBhbHNvIHB2YWx1ZSA8MC4wNSAKc2lnbmlmaWNhbnRfcHFfcmVzIDwtIHNpZ25pZmljYW50X3BxX3Jlc3VsdHNbb3JkZXIoYWJzKHNpZ25pZmljYW50X3BxX3Jlc3VsdHMkZGlmZmVyZW5jZS5sb25nLnZzLnNob3J0KSwgZGVjcmVhc2luZyA9IFRSVUUpLCBdCgojIFZpZXcgdGhlIHRvcCAxMCBtb3N0IHNpZ25pZmljYW50IGhpdHMKdG9wX3NpZ25pZmljYW50X3BxIDwtIGhlYWQoc2lnbmlmaWNhbnRfcHFfcmVzLCAxMCkgIAojUHJpbnQgdG9wIDEwCnByaW50KHRvcF9zaWduaWZpY2FudF9wcSkKCmBgYAoKCmBgYHtyfQoKI3ZvbGNhbm8gcGxvdCBmb3IgZGlmZmVyZW50aWFsIGV4cHJlc3Npb24gcmVzdWx0cyAKCmdncGxvdChkZi5saW1tYS5xdWFudCwgYWVzKHggPSBkaWZmZXJlbmNlLmxvbmcudnMuc2hvcnQsIHkgPSAtbG9nMTAocHZhbHVlcykpKSArCiAgICBnZW9tX3BvaW50KGFlcyhjb2xvciA9IHB2YWx1ZXMgPCBwdmFsX3RocmVzaG9sZCkpICsKICAgIHRoZW1lX21pbmltYWwoKSArCiAgICBsYWJzKHRpdGxlID0gIlZvbGNhbm8gUGxvdCBmb3IgUHJvdGVpbiBRdWFudGlmaWNhdGlvbiBEYXRhIiwgCiAgICAgICAgIHggPSAiTG9nMiBGb2xkIENoYW5nZSIsIAogICAgICAgICB5ID0gIi1sb2cxMChwLXZhbHVlKSIpICsKICAgIGdlb21fdGV4dF9yZXBlbChkYXRhID0gdG9wX3NpZ25pZmljYW50X3BxLCAjb24gdGV4dCB0aGUgdG9wIDEwIHJlc3VsdHMgCiAgICAgICAgICAgICAgICAgICAgYWVzKGxhYmVsID0gWCksCiAgICAgICAgICAgICAgICAgICAgc2l6ZSA9IDMsIAogICAgICAgICAgICAgICAgICAgIG1heC5vdmVybGFwcyA9IEluZikgKyAgIyBVc2UgSW5mIHRvIGF2b2lkIGZpbHRlcmluZyBvdXQgdG9wIDUKICAgIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjKCJyZWQiLCAiYmx1ZSIpLCBuYW1lID0gInB2YWx1ZXMgPCAwLjA1IikgKwogICAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gInJpZ2h0IikKYGBgCgoKUGF0aHdheSBlbnJpY2htZW50IGFuYWx5c2lzOgoKR08gRW5yaWNobWVudCAKCgpgYGB7cn0KCiMgdGhlc2UgYXJlIGluIHRoZSBmb3JtYXQgb2YgVW5pUHJvdCBpZGVudGlmaWVycyAtIHNvIGV4dHJhY3QgdGhlbSB0byBiZSB1c2VkIGluIHRoZSBhbmFseXNpcyAKdW5pcHJvdF9pZHMgPC0gc2lnbmlmaWNhbnRfcHFfcmVzdWx0cyRYIAoKIyBFeHRyYWN0IGdlbmUgc3ltYm9scyBmcm9tIHBob3NwaG9wcm90ZWluIElEcyAtIHRoZXkgYXJlIGluIHRoZSBmb3JtYXQgR0VORV9IVU1BTgpzaWduaWZpY2FudF9wcSA8LSB1bmlxdWUoZ3N1YigiX0hVTUFOIiwgIiIsIHVuaXByb3RfaWRzKSkKCiMgQ29udmVydCBnZW5lIHN5bWJvbHMgdG8gRW50cmV6IElEcwplbnRyZXpfaWRzX3BxIDwtIGJpdHIoc2lnbmlmaWNhbnRfcHEsIGZyb21UeXBlID0gIlNZTUJPTCIsIHRvVHlwZSA9ICJFTlRSRVpJRCIsIE9yZ0RiID0gb3JnLkhzLmVnLmRiKQojNTAuNTklIG9mIGlucHV0IGdlbmUgSURzIGFyZSBmYWlsIHRvIG1hcC4uLgojdHJpZWQgdG8gdXNlIHRoZSBiaXRyX2tlZ2cgZnVuY3Rpb24gdG8gY29udmVydCBVbmlQcm90IElEcyB0byBFbnRyZXogSURzOiAxMDAlIGZhaWxlZCB0byBtYXAKCgojIFBlcmZvcm0gR08gZW5yaWNobWVudCBhbmFseXNpcyAtIHVzZWQgdW5hZGp1c3RlZCBmb3IgdGhlc2UgdG8geWllbGQgcmVzdWx0cwoKZ29fcHFfZW5yaWNobWVudCA8LSBlbnJpY2hHTyhnZW5lID0gZW50cmV6X2lkc19wcSRFTlRSRVpJRCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgT3JnRGIgPSBvcmcuSHMuZWcuZGIsIAogICAgICAgICAgICAgICAgICAgICAgICAgIG9udCA9ICJCUCIsICMgIkJQIiBmb3IgQmlvbG9naWNhbCBQcm9jZXNzZXMKICAgICAgICAgICAgICAgICAgICAgICAgICBwQWRqdXN0TWV0aG9kID0gIm5vbmUiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICBwdmFsdWVDdXRvZmYgPSAwLjAxLCAKICAgICAgICAgICAgICAgICAgICAgICAgICBxdmFsdWVDdXRvZmYgPSAwLjIsIAogICAgICAgICAgICAgICAgICAgICAgICAgIHJlYWRhYmxlID0gVFJVRSkKCgojIG90aGVyIGNhdGVnb3JpZXMgKE1GLCBDQykKZ29fZW5yaWNobWVudF9wcV9NRiA8LSBlbnJpY2hHTyhnZW5lID0gZW50cmV6X2lkc19wcSRFTlRSRVpJRCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgT3JnRGIgPSBvcmcuSHMuZWcuZGIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9udCA9ICJNRiIsICNtb2xlY3VsYXIgZnVuY3Rpb24KICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwQWRqdXN0TWV0aG9kID0gIkJIIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHZhbHVlQ3V0b2ZmID0gMC4wNSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcXZhbHVlQ3V0b2ZmID0gMC4yLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWFkYWJsZSA9IFRSVUUpCgoKZ29fZW5yaWNobWVudF9wcV9DQyA8LSBlbnJpY2hHTyhnZW5lID0gZW50cmV6X2lkc19wcSRFTlRSRVpJRCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgT3JnRGIgPSBvcmcuSHMuZWcuZGIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9udCA9ICJDQyIsICNjZWxsdWxhciBjb21wb25lbnRzCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcEFkanVzdE1ldGhvZCA9ICJub25lIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHZhbHVlQ3V0b2ZmID0gMC4wMSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcXZhbHVlQ3V0b2ZmID0gMC4yLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWFkYWJsZSA9IFRSVUUpCgoKCmBgYAoKYGBge3J9CgojIFZpc3VhbGl6ZSBmb3IgR08gYmlvbG9naWNhbCBwcm9jZXNzZXMgcGF0aHdheXMgCmJhcnBsb3QoZ29fcHFfZW5yaWNobWVudCwgc2hvd0NhdGVnb3J5ID0gMTAsIHRpdGxlID0gIkdPIEJpb2xvZ2ljYWwgUHJvY2Vzc2VzIEVucmljaG1lbnQiKQpkb3RwbG90KGdvX3BxX2VucmljaG1lbnQsIHNob3dDYXRlZ29yeSA9IDEwLCB0aXRsZSA9ICJHTyBCaW9sb2dpY2FsIFByb2Nlc3NlcyBFbnJpY2htZW50IikKCiMgVXNlIGhlYXRwbG90IApoZWF0cGxvdChnb19wcV9lbnJpY2htZW50LCBzaG93Q2F0ZWdvcnkgPSAxMCkKCmBgYAoKYGBge3J9CiNuZXR3b3JrIHBsb3QKY25ldHBsb3QoZ29fcHFfZW5yaWNobWVudCwgc2hvd0NhdGVnb3J5ID0gNCwgdGl0bGUgPSAiR2VuZS1Db25jZXB0IE5ldHdvcmsgZm9yIEJpb2xvZ2ljYWwgUHJvY2Vzc2VzIiwgCiAgICAgICAgIG1heC5vdmVybGFwcyA9IDEwMCwgbm9kZV9sYWJlbF9zaXplID0gMywgbGFiZWxfZm9udHNpemUgPSA4KSArCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwKSwgCiAgICAgICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwKSwgCiAgICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTQsIGZhY2UgPSAiYm9sZCIpKQoKI2RlY2lkZWQgb24gdGhlIG51bWJlciA0IGZvciB0aGUgY2F0ZWdvcmllcywgYXMgaGlnaGVyIG51bWJlciBvdmVyd2hlbG1zIHRoZSBwbG90IGFuZCBkYXRhIHBvaW50cyB3ZXJlIHVubGFiZWxlZCAKYGBgCgpgYGB7cn0KIyBWaXN1YWxpemUgTUYsIENDCgpkb3RwbG90KGdvX2VucmljaG1lbnRfcHFfQ0MsIHNob3dDYXRlZ29yeSA9IDEwLCB0aXRsZSA9ICJHTyBDZWxsdWxhciBDb21wb25lbnRzIEVucmljaG1lbnQiKQpgYGAKCkZvciBzcGVjaWZpY2FsbHkgYmFkLXJlc3BvbmRlcnMvIHRhcmdldHMgYXNzb2NpYXRlZCB3aXRoIHNob3J0IHN1cnZpdmFsIGdyb3VwOgoKYGBge3J9CiNzdWJzZXQgdGhlIHJlc3VsdHMsIGtlZXBpbmcgb25seSB0aGUgZmVhdHVyZXMgdXByZWd1bGFyZWQgaW4gdGhlIHNob3J0IHN1cnZpdmFsIGdyb3VwIApzdWJzZXRfcHEgPC0gc3Vic2V0KHNpZ25pZmljYW50X3BxX3Jlc3VsdHMsIGRpZmZlcmVuY2UubG9uZy52cy5zaG9ydCA+IDApCiNjbGVhbiB0aGUgZGF0YSAtIHJlYWR5IGZvciB0aGUgR08gZW5yaWNobWVudCBhbmFseXNpcyAKY2xlYW5fc3Vic2V0X3BxIDwtIHVuaXF1ZShnc3ViKCJfSFVNQU4iLCAiIiwgc3Vic2V0X3BxJFgpKQoKIyBDb252ZXJ0IHRoZXNlIGtpbmFzZSBuYW1lcyB0byBFbnRyZXogSURzCmVuX2lkc19wcSA8LSBiaXRyKGNsZWFuX3N1YnNldF9wcSwgZnJvbVR5cGUgPSAiU1lNQk9MIiwgdG9UeXBlID0gIkVOVFJFWklEIiwgT3JnRGIgPSBvcmcuSHMuZWcuZGIpCgojR08gZW5yaWNobWVudCAKZ29fcHFfcF9lbnJpY2htZW50IDwtIGVucmljaEdPKGdlbmUgPSBlbl9pZHNfcHEkRU5UUkVaSUQsIAogICAgICAgICAgICAgICAgICAgICAgICAgIE9yZ0RiID0gb3JnLkhzLmVnLmRiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICBvbnQgPSAiQlAiLCAjICJCUCIgZm9yIEJpb2xvZ2ljYWwgUHJvY2Vzc2VzCiAgICAgICAgICAgICAgICAgICAgICAgICAgcEFkanVzdE1ldGhvZCA9ICJCSCIsIAogICAgICAgICAgICAgICAgICAgICAgICAgIHB2YWx1ZUN1dG9mZiA9IDAuMDUsIAogICAgICAgICAgICAgICAgICAgICAgICAgIHF2YWx1ZUN1dG9mZiA9IDAuMiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgcmVhZGFibGUgPSBUUlVFKQoKCiNQbG90cwpiYXJwbG90KGdvX3BxX3BfZW5yaWNobWVudCwgc2hvd0NhdGVnb3J5ID0gMTAsIHRpdGxlID0gIkdPIEJpb2xvZ2ljYWwgUHJvY2Vzc2VzIGVucmljaGVkIGluIHNob3J0IHN1cnZpdmFsIGdyb3VwIikKZG90cGxvdChnb19wcV9wX2VucmljaG1lbnQsIHNob3dDYXRlZ29yeSA9IDEwLCB0aXRsZSA9ICJHTyBCaW9sb2dpY2FsIFByb2Nlc3NlcyBlbnJpY2hlZCBpbiBzaG9ydCBzdXJ2aXZhbCBncm91cCIpCmhlYXRwbG90KGdvX3BxX3BfZW5yaWNobWVudCwgc2hvd0NhdGVnb3J5ID0gMTApCgoKI25ldHdvcmsgcGxvdCAKY25ldHBsb3QoZ29fcHFfcF9lbnJpY2htZW50LCBzaG93Q2F0ZWdvcnkgPSA1LCB0aXRsZSA9ICJHZW5lLUNvbmNlcHQgTmV0d29yayBmb3IgQmlvbG9naWNhbCBQcm9jZXNzZXMiLCAKICAgICAgICAgbWF4Lm92ZXJsYXBzID0gMTAwLCBub2RlX2xhYmVsX3NpemUgPSAzLCBsYWJlbF9mb250c2l6ZSA9IDgpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTApLCAKICAgICAgICBheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTApLCAKICAgICAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCwgZmFjZSA9ICJib2xkIikpCiNkZWNpZGVkIG9uIDUgdG8gbm90IG92ZXJ3aGVsbSB0aGUgcGxvdCAKYGBgCgoKVXNpbmcgZ3Byb2ZpbGVyMiAvIHVzZWQgYWxsIHRoZSBzaWduaWZpY2FudCBkaWZmZXJlbnRpYWxseSBleHByZXNzZWQgcmVzdWx0czogCgpgYGB7cn0KI2dvc3QgZnVuY3Rpb24KZ29zdHJlc19wcSA8LSBnb3N0KHF1ZXJ5ID0gc2lnbmlmaWNhbnRfcHEsIAogICAgICAgICAgICAgICAgb3JnYW5pc20gPSAiaHNhcGllbnMiLCAKICAgICAgICAgICAgICAgIHNvdXJjZXMgPSBjKCJHTzpCUCIsICJHTzpNRiIsICJHTzpDQyIsICJLRUdHIiwgIlJFQUMiLCAiV1AiKSwgCiAgICAgICAgICAgICAgICBzaWduaWZpY2FudCA9IFRSVUUsIAogICAgICAgICAgICAgICAgY29ycmVjdGlvbl9tZXRob2QgPSAiZmRyIiwgIAogICAgICAgICAgICAgICAgdXNlcl90aHJlc2hvbGQgPSAwLjA1KQoKIyBWaWV3IHJlc3VsdHMKaGVhZChnb3N0cmVzX3BxJHJlc3VsdCkKCiMgUGxvdCAKZ29zdHBsb3QoZ29zdHJlc19wcSwgY2FwcGVkID0gVFJVRSwgaW50ZXJhY3RpdmUgPSBGQUxTRSkKYGBgCgpgYGB7cn0KCiMgUGxvdCBmb3IgZWFjaCBjYXRlZ29yeSAoR08sIEtFR0csIFJFQUNUT01FLCBXSUtJUEFUSFdBWVMpCmJwX3Bsb3RfcHEgPC0gcGxvdF9yZXN1bHRzKGdvc3RyZXNfcHEkcmVzdWx0LCAiR086QlAiLCAiVG9wIEJpb2xvZ2ljYWwgUHJvY2Vzc2VzIikKbWZfcGxvdF9wcSA8LSBwbG90X3Jlc3VsdHMoZ29zdHJlc19wcSRyZXN1bHQsICJHTzpNRiIsICJUb3AgTW9sZWN1bGFyIEZ1bmN0aW9ucyIpCmNjX3Bsb3RfcHEgPC0gcGxvdF9yZXN1bHRzKGdvc3RyZXNfcHEkcmVzdWx0LCAiR086Q0MiLCAiVG9wIENlbGx1bGFyIENvbXBvbmVudHMiKQpyZWFjX3Bsb3RfcHEgPC0gcGxvdF9yZXN1bHRzKGdvc3RyZXNfcHEkcmVzdWx0LCAiUkVBQyIsICJUb3AgUmVhY3RvbWUgUGF0aHdheXMiKQprZWdnX3Bsb3RfcHEgPC0gcGxvdF9yZXN1bHRzKGdvc3RyZXNfcHEkcmVzdWx0LCAiS0VHRyIsICJUb3AgS0VHRyBQYXRod2F5cyIpCndwX3Bsb3RfcHEgPC0gcGxvdF9yZXN1bHRzKGdvc3RyZXNfcHEkcmVzdWx0LCAiV1AiLCAiVG9wIFdpa2lQYXRod2F5cyIpCgojIFByaW50IHBsb3RzCnByaW50KGJwX3Bsb3RfcHEpCnByaW50KG1mX3Bsb3RfcHEpCnByaW50KGNjX3Bsb3RfcHEpCnByaW50KHJlYWNfcGxvdF9wcSkgI05vIFJlYWN0b21lIHBhdGh3YXlzIGlkZW50ZmllZCAKcHJpbnQoa2VnZ19wbG90X3BxKSAgI05vIEtFR0cgcGF0aHdheXMgaWRlbnRmaWVkIApwcmludCh3cF9wbG90X3BxKSAgI05vIFdpa2lQYXRod2F5cyBwYXRod2F5cyBpZGVudGZpZWQgCmBgYAoKCgpLU0VBIGRhdGE6IAoKYGBge3J9CiMgRmlsdGVyIEtTRUEgZGF0YQpLU0VBX2ZpbHRlcmVkIDwtIGtzZWFfZGF0YSAlPiUKICBkcGx5cjo6c2VsZWN0KFgsIGFsbF9vZihzaG9ydF9zYW1wbGVzKSwgYWxsX29mKGxvbmdfc2FtcGxlcykpCgpkaW0oS1NFQV9maWx0ZXJlZCkKYGBgCgpQcmUtcHJvY2Vzc2luZyBzdGVwczoKCm5lZWQgdG8gZmlyc3QgcGVyZm9ybSB0aGlzIHN0ZXAsIGFzIGRhdGEgY29udGFpbnMgbWlzc2luZyhOQSkvbm9uLW51bWVyaWMgdmFsdWVzCmBgYHtyfQojIFJlcGxhY2UgemVyb3MgYW5kIG5lZ2F0aXZlIHZhbHVlcyB0byBhdm9pZCBpc3N1ZXMgd2l0aCBsb2cyCiNhIHNtYWxsIGNvbnN0YW50IHdhcyB1c2VkIHRvIHJlcGxhY2UgemVyb3MgYW5kIG5lZ2F0aXZlIHZhbHVlcyAKS1NFQV9maWx0ZXJlZFssIC0xXSA8LSBhcHBseShLU0VBX2ZpbHRlcmVkWywgLTFdLCAyLCBmdW5jdGlvbih4KSB7CiAgeFt4IDw9IDBdIDwtIG1pbih4W3ggPiAwXSwgbmEucm0gPSBUUlVFKSAvIDEwICAjIHNtYWxsIGNvbnN0YW50IHRvIGhhbmRsZSB6ZXJvcyBvciBuZWdhdGl2ZSB2YWx1ZXMKICByZXR1cm4oeCkKfSkKYGBgCgoKYGBge3J9CgojIEJveHBsb3QgYmVmb3JlIHByZXByb2Nlc3NpbmcgdG8gY2hlY2sgZGlzdHJpYnV0aW9uCmJveHBsb3QoS1NFQV9maWx0ZXJlZFssIC0xXSwgbGFzID0gMywgbWFpbiA9ICJLU0VBIERhdGEgRGlzdHJpYnV0aW9uIEJlZm9yZSBQcmVwcm9jZXNzaW5nIiwgY2V4Lm1haW4gPSAyKQoKI2ZpbHRlcmVkLCBidXQgd2l0aCBhIGxvd2VyIHRocmVzaG9sZCAKS1NFQV9maWx0ZXJlZCA8LSBLU0VBX2ZpbHRlcmVkW3Jvd1N1bXMoS1NFQV9maWx0ZXJlZFssIC0xXSA+IDEpID49IDIsIF0KCiMgTG9nMiB0cmFuc2Zvcm1hdGlvbgpsb2cyX3RyYW5zZm9ybWVkIDwtIEtTRUFfZmlsdGVyZWQKbG9nMl90cmFuc2Zvcm1lZFssIC0xXSA8LSBsb2cyKEtTRUFfZmlsdGVyZWRbLCAtMV0gKyAxKQoKIyBRdWFudGlsZSBub3JtYWxpemF0aW9uCnF1YW50aWxlX25vcm1hbGl6ZWQgPC0gbG9nMl90cmFuc2Zvcm1lZApxdWFudGlsZV9ub3JtYWxpemVkWywgLTFdIDwtIG5vcm1hbGl6ZS5xdWFudGlsZXMoYXMubWF0cml4KGxvZzJfdHJhbnNmb3JtZWRbLCAtMV0pKQoKIyBTY2FsaW5nIChjZW50ZXJpbmcgYW5kIHNjYWxpbmcpCnNjYWxlZCA8LSBxdWFudGlsZV9ub3JtYWxpemVkCnNjYWxlZFssIC0xXSA8LSBzY2FsZShhcy5tYXRyaXgocXVhbnRpbGVfbm9ybWFsaXplZFssIC0xXSksIGNlbnRlciA9IFRSVUUsIHNjYWxlID0gVFJVRSkKCiMgQ3JlYXRlIHRoZSBmaW5hbCBwcmVwcm9jZXNzZWQgZGF0YXNldApLU0VBX2ZpbmFsIDwtIHNjYWxlZAoKIyBCb3hwbG90IGFmdGVyIHByZXByb2Nlc3NpbmcKYm94cGxvdChLU0VBX2ZpbmFsWywgLTFdLCBsYXMgPSAzLCBtYWluID0gIktTRUEgRGF0YSBEaXN0cmlidXRpb24gQWZ0ZXIgUHJlcHJvY2Vzc2luZyAoTG9nMiwgUXVhbnRpbGUgTm9ybWFsaXphdGlvbiwgU2NhbGluZykiLCBjZXgubWFpbiA9IDIpCgpgYGAKCkRpZmZlcmVudGlhbCBleHByZXNzaW9uIGFuYWx5c2lzOgoKYGBge3J9CiMgUGVyZm9ybSBkaWZmZXJlbnRpYWwgZXhwcmVzc2lvbiBhbmFseXNpcwpkZi5saW1tYS5rc2VhIDwtIGNvbXBhcmUuYnkubGltbWEoS1NFQV9maW5hbCwgbG9uZ19zYW1wbGVzLCBzaG9ydF9zYW1wbGVzKQoKIyBEZWZpbmUgdGhlIHAtdmFsdWUgdGhyZXNob2xkIGZvciBzaWduaWZpY2FuY2UKcF92YWx1ZV90aHJlc2hvbGQgPC0gMC4wNQoKIyBGaWx0ZXIgc2lnbmlmaWNhbnQgcmVzdWx0cyBiYXNlZCBvbiBwLXZhbHVlCnNpZ25pZmljYW50X2tzZWFfcmVzdWx0cyA8LSBkZi5saW1tYS5rc2VhW2RmLmxpbW1hLmtzZWEkcHZhbHVlcyA8IHBfdmFsdWVfdGhyZXNob2xkLCBdCgojIFByaW50IHNpZ25pZmljYW50IHJlc3VsdHMKcHJpbnQoc2lnbmlmaWNhbnRfa3NlYV9yZXN1bHRzKQoKIyBPcmRlciB0aGUgc2lnbmlmaWNhbnQgcmVzdWx0cyBieSBhYnNvbHV0ZSBkaWZmZXJlbnRpYWwgZXhwcmVzc2lvbiAvIG1vc3QgZXhwcmVzc2VkIGJ1dCBhbHNvIHB2YWx1ZSA8MC4wNSAKc2lnbmlmaWNhbnRfa3NlYV9yZXMgPC0gc2lnbmlmaWNhbnRfa3NlYV9yZXN1bHRzW29yZGVyKGFicyhzaWduaWZpY2FudF9rc2VhX3Jlc3VsdHMkZGlmZmVyZW5jZS5sb25nLnZzLnNob3J0KSwgZGVjcmVhc2luZyA9IFRSVUUpLCBdCgojIFZpZXcgdGhlIHRvcCBtb3N0IHNpZ25pZmljYW50IGhpdHMKdG9wX3NpZ25pZmljYW50X2tzZWEgPC0gaGVhZChzaWduaWZpY2FudF9rc2VhX3JlcywgMTApIAojcHJpbnQgdG9wIDEwCnByaW50KHRvcF9zaWduaWZpY2FudF9rc2VhKQoKYGBgCgoKYGBge3J9CiN2b2xjYW5vIHBsb3Qgb2YgZGlmZmVyZW50aWFsIGV4cHJlc3Npb24gcmVzdWx0cyAKCmdncGxvdChkZi5saW1tYS5rc2VhLCBhZXMoeCA9IGRpZmZlcmVuY2UubG9uZy52cy5zaG9ydCwgeSA9IC1sb2cxMChwdmFsdWVzKSkpICsKICAgIGdlb21fcG9pbnQoYWVzKGNvbG9yID0gcHZhbHVlcyA8IHB2YWxfdGhyZXNob2xkKSkgKwogICAgdGhlbWVfbWluaW1hbCgpICsKICAgIGxhYnModGl0bGUgPSAiVm9sY2FubyBQbG90IGZvciBLU0VBIERhdGEiLCAKICAgICAgICAgeCA9ICJMb2cyIEZvbGQgQ2hhbmdlIiwgCiAgICAgICAgIHkgPSAiLWxvZzEwKHAtdmFsdWUpIikgKwogICAgZ2VvbV90ZXh0X3JlcGVsKGRhdGEgPSB0b3Bfc2lnbmlmaWNhbnRfa3NlYSwgI3RvcCAxMCByZXN1bHRzIGRpc3BsYXllZCBpbiB0aGUgcGxvdCAKICAgICAgICAgICAgICAgICAgICBhZXMobGFiZWwgPSBYKSwKICAgICAgICAgICAgICAgICAgICBzaXplID0gMywgCiAgICAgICAgICAgICAgICAgICAgbWF4Lm92ZXJsYXBzID0gSW5mKSArICAjIFVzZSBJbmYgdG8gYXZvaWQgZmlsdGVyaW5nIG91dCB0b3AgNQogICAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGMoInJlZCIsICJibHVlIiksIG5hbWUgPSAicHZhbHVlcyA8IDAuMDUiKSArCiAgICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAicmlnaHQiKQpgYGAKCgoKUGF0aHdheSBlbnJpY2hlbnQgYW5hbHlzaXM6IAoKR08gRW5yaWNobWVudCAKCgpgYGB7cn0KIyBIYXZlIHRvIGNyZWF0ZSBhIGxpc3QgdG8gaW5zZXJ0IHRvIHBhdGh3YXkgZW5yaWNobWVudCBhbmFseXNpcwojIEV4dHJhY3QgaW5kaXZpZHVhbCBraW5hc2UgbmFtZXMgZnJvbSB0aGUgcGFpcnMKaW5kaXZpZHVhbF9raW5hc2VzIDwtIHVuaXF1ZSh1bmxpc3Qoc3Ryc3BsaXQoc2lnbmlmaWNhbnRfa3NlYV9yZXN1bHRzJFgsICJcXC4iKSkpCgojIFJlbW92ZSB1bndhbnRlZCB0ZXJtcywgbWFpbmx5IHNpZ25vciwgb3IgZWRnZXMKaW5kaXZpZHVhbF9raW5hc2VzIDwtIGluZGl2aWR1YWxfa2luYXNlc1shaW5kaXZpZHVhbF9raW5hc2VzICVpbiUgYygic2lnbm9yIiwgImVkZ2VzIildCgojIFRoZXJlIGlzIHRoaXMgIk1BUEsxXzMiIG9uIHRoZSBsaXN0LCB3aGljaCBpcyB0aGUgTUFQSzEgYW5kIHRoZSBNQVBLMyAKaW5kaXZpZHVhbF9raW5hc2VzIDwtIGMoaW5kaXZpZHVhbF9raW5hc2VzLCAiTUFQSzEiLCAiTUFQSzMiKQoKIyBDb252ZXJ0IHRoZXNlIGtpbmFzZSBuYW1lcyB0byBFbnRyZXogSURzCmtpbmFzZV9lbnRyZXpfaWRzX2luZGl2aWR1YWwgPC0gYml0cihpbmRpdmlkdWFsX2tpbmFzZXMsIGZyb21UeXBlID0gIlNZTUJPTCIsIHRvVHlwZSA9ICJFTlRSRVpJRCIsIE9yZ0RiID0gb3JnLkhzLmVnLmRiKQojMTAlIHNheXMgd2FzIG5vdCBtYXBwZWQsIGJ1dCBpdCB3YXMgdGhlICJNQVBLMV8zIiwgc28gZXZlcnl0aGluZyBlbHNlIHdhcyBtYXBwZWQgc3VjY2Vzc2Z1bGx5CgpgYGAKCmBgYHtyfQoKI3BlcmZvcm0gR08gZW5yaWNobWVudCAKZ29fa3NlYV9lbnJpY2htZW50IDwtIGVucmljaEdPKGdlbmUgPSBraW5hc2VfZW50cmV6X2lkc19pbmRpdmlkdWFsJEVOVFJFWklELCAKICAgICAgICAgICAgICAgICAgICAgICAgICBPcmdEYiA9IG9yZy5Icy5lZy5kYiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgb250ID0gIkJQIiwgIyAiQlAiIGZvciBCaW9sb2dpY2FsIFByb2Nlc3NlcwogICAgICAgICAgICAgICAgICAgICAgICAgIHBBZGp1c3RNZXRob2QgPSAiQkgiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICBwdmFsdWVDdXRvZmYgPSAwLjA1LCAKICAgICAgICAgICAgICAgICAgICAgICAgICBxdmFsdWVDdXRvZmYgPSAwLjIsIAogICAgICAgICAgICAgICAgICAgICAgICAgIHJlYWRhYmxlID0gVFJVRSkKCgojIG90aGVyIGNhdGVnb3JpZXMgKE1GLCBDQykKZ29fZW5yaWNobWVudF9rc2VhX01GIDwtIGVucmljaEdPKGdlbmUgPSBraW5hc2VfZW50cmV6X2lkc19pbmRpdmlkdWFsJEVOVFJFWklELCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBPcmdEYiA9IG9yZy5Icy5lZy5kYiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb250ID0gIk1GIiwgI21vbGVjdWxhciBmdW5jdGlvbnMKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwQWRqdXN0TWV0aG9kID0gIkJIIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHZhbHVlQ3V0b2ZmID0gMC4wNSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcXZhbHVlQ3V0b2ZmID0gMC4yLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWFkYWJsZSA9IFRSVUUpCgoKZ29fZW5yaWNobWVudF9rc2VhX0NDIDwtIGVucmljaEdPKGdlbmUgPSBraW5hc2VfZW50cmV6X2lkc19pbmRpdmlkdWFsJEVOVFJFWklELCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBPcmdEYiA9IG9yZy5Icy5lZy5kYiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb250ID0gIkNDIiwgI2NlbGx1bGFyIGNvbXBvbmVudHMKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwQWRqdXN0TWV0aG9kID0gIkJIIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHZhbHVlQ3V0b2ZmID0gMC4wNSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcXZhbHVlQ3V0b2ZmID0gMC4yLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWFkYWJsZSA9IFRSVUUpCgoKCmBgYAoKYGBge3J9CgojIFZpc3VhbGl6ZSBmb3IgR08gYmlvbG9naWNhbCBwcm9jZXNzZXMgcGF0aHdheXMgCmJhcnBsb3QoZ29fa3NlYV9lbnJpY2htZW50LCBzaG93Q2F0ZWdvcnkgPSAxMCwgdGl0bGUgPSAiR08gQmlvbG9naWNhbCBQcm9jZXNzZXMgRW5yaWNobWVudCIpCmRvdHBsb3QoZ29fa3NlYV9lbnJpY2htZW50LCBzaG93Q2F0ZWdvcnkgPSAxMCwgdGl0bGUgPSAiR08gQmlvbG9naWNhbCBQcm9jZXNzZXMgRW5yaWNobWVudCIpCgojIFVzZSBoZWF0cGxvdCAKaGVhdHBsb3QoZ29fa3NlYV9lbnJpY2htZW50LCBzaG93Q2F0ZWdvcnkgPSAxMCkKCgpgYGAKCmBgYHtyfQojbmV0d29yayBwbG90IApjbmV0cGxvdChnb19rc2VhX2VucmljaG1lbnQsIHNob3dDYXRlZ29yeSA9IDUsIHRpdGxlID0gIkdlbmUtQ29uY2VwdCBOZXR3b3JrIGZvciBCaW9sb2dpY2FsIFByb2Nlc3NlcyIsIAogICAgICAgICBtYXgub3ZlcmxhcHMgPSAxMDAsIG5vZGVfbGFiZWxfc2l6ZSA9IDMsIGxhYmVsX2ZvbnRzaXplID0gOCkgKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCksIAogICAgICAgIGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCksIAogICAgICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE0LCBmYWNlID0gImJvbGQiKSkKCiNkZWNpZGVkIG9uIDUgdG8gbm90IG92ZXJ3aGVsbSB0aGUgcGxvdCAKYGBgCgpgYGB7cn0KIyBWaXN1YWxpemUgTUYsIENDCgpkb3RwbG90KGdvX2VucmljaG1lbnRfa3NlYV9NRiwgc2hvd0NhdGVnb3J5ID0gMTAsIHRpdGxlID0gIkdPIE1vbGVjdWxhciBGdW5jdGlvbnMgRW5yaWNobWVudCIpCmRvdHBsb3QoZ29fZW5yaWNobWVudF9rc2VhX0NDLCBzaG93Q2F0ZWdvcnkgPSAxMCwgdGl0bGUgPSAiR08gQ2VsbHVsYXIgQ29tcG9uZW50cyBFbnJpY2htZW50IikKYGBgCgoKRm9yIHNwZWNpZmljYWxseSBiYWQtcmVzcG9uZGVycy8gdGFyZ2V0cyBhc3NvY2lhdGVkIHdpdGggc2hvcnQgc3Vydml2YWwgb3V0Y29tZXMgZ3JvdXA6CgpgYGB7cn0KIyBTdWJzZXQgdGhlIGRhdGEsIGtlZXBpbmcgb25seSB0aGUgc2lnbmlmaWNhbnQgZmVhdHVyZXMgdXByZWd1bGF0ZWQgaW4gdGhlIHNob3J0IHN1cnZpdmFsIGdyb3VwIApzdWJzZXRfa3NlYSA8LSBzdWJzZXQoc2lnbmlmaWNhbnRfa3NlYV9yZXN1bHRzLCBkaWZmZXJlbmNlLmxvbmcudnMuc2hvcnQgPiAwKQojIENsZWFuIHRoZSBkYXRhLCByZWFkeSBmb3IgYW5sYWx5c2lzIApzdWJzZXRfa3NlYSA8LSB1bmlxdWUodW5saXN0KHN0cnNwbGl0KHN1YnNldF9rc2VhJFgsICJcXC4iKSkpCgojIFJlbW92ZSB0aGUgdW53YW50ZWQgdGVybXMKc3Vic2V0X2tzZWEgPC0gc3Vic2V0X3Jlc3VsdHM0WyFzdWJzZXRfa3NlYSAlaW4lIGMoInNpZ25vciIsICJlZGdlcyIpXQoKIyJNSU5LMSIgd2FzIG5vdCBpbmNsdWRlZCBzbyBJIGFkZGVkIGl0IApzdWJzZXRfa3NlYSA8LSBjKHN1YnNldF9rc2VhLCAiTUlOSzEiKQoKIyBDb252ZXJ0IHRoZXNlIGtpbmFzZSBuYW1lcyB0byBFbnRyZXogSURzCmVuX2lkc19rc2VhIDwtIGJpdHIoc3Vic2V0X2tzZWEsIGZyb21UeXBlID0gIlNZTUJPTCIsIHRvVHlwZSA9ICJFTlRSRVpJRCIsIE9yZ0RiID0gb3JnLkhzLmVnLmRiKQojb25seSAiTUFQSzFfMyIgbm90IG1hcHBlZCwgYnV0IE1BUEsxIGFuZCBNQVBLMyBtYXBwZWQgCgojR08gZW5yaWNobWVudCAKZ29fa3NlYV9wX2VucmljaG1lbnQgPC0gZW5yaWNoR08oZ2VuZSA9IGVuX2lkc19rc2VhJEVOVFJFWklELCAKICAgICAgICAgICAgICAgICAgICAgICAgICBPcmdEYiA9IG9yZy5Icy5lZy5kYiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgb250ID0gIkJQIiwgIyAiQlAiIGZvciBCaW9sb2dpY2FsIFByb2Nlc3NlcwogICAgICAgICAgICAgICAgICAgICAgICAgIHBBZGp1c3RNZXRob2QgPSAiQkgiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICBwdmFsdWVDdXRvZmYgPSAwLjA1LCAKICAgICAgICAgICAgICAgICAgICAgICAgICBxdmFsdWVDdXRvZmYgPSAwLjIsIAogICAgICAgICAgICAgICAgICAgICAgICAgIHJlYWRhYmxlID0gVFJVRSkKCgojUGxvdHMKYmFycGxvdChnb19rc2VhX3BfZW5yaWNobWVudCwgc2hvd0NhdGVnb3J5ID0gMTAsIHRpdGxlID0gIkdPIEJpb2xvZ2ljYWwgUHJvY2Vzc2VzIGVucmljaGVkIGluIHNob3J0IHN1cnZpdmFsIGdyb3VwIikKZG90cGxvdChnb19rc2VhX3BfZW5yaWNobWVudCwgc2hvd0NhdGVnb3J5ID0gMTAsIHRpdGxlID0gIkdPIEJpb2xvZ2ljYWwgUHJvY2Vzc2VzIGVucmljaGVkIGluIHNob3J0IHN1cnZpdmFsIGdyb3VwIikKaGVhdHBsb3QoZ29fa3NlYV9wX2VucmljaG1lbnQsIHNob3dDYXRlZ29yeSA9IDEwKQoKCiNuZXR3b3JrIHBsb3QgCmNuZXRwbG90KGdvX2tzZWFfcF9lbnJpY2htZW50LCBzaG93Q2F0ZWdvcnkgPSA1LCB0aXRsZSA9ICJHZW5lLUNvbmNlcHQgTmV0d29yayBmb3IgQmlvbG9naWNhbCBQcm9jZXNzZXMgZW5yaWNoZWQgaW4gc2hvcnQgc3Vydml2YWwgZ3JvdXAiLCAKICAgICAgICAgbWF4Lm92ZXJsYXBzID0gMTAwLCBub2RlX2xhYmVsX3NpemUgPSAzLCBsYWJlbF9mb250c2l6ZSA9IDgpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTApLCAKICAgICAgICBheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTApLCAKICAgICAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCwgZmFjZSA9ICJib2xkIikpCiNkZWNpZGVkIG9uIDUgdG8gbm90IG92ZXJ3aGVsbSB0aGUgcGxvdCAKYGBgCgoKClVzaW5nIGdwcm9maWxlcjIgLyB1c2luZyBhbGwgc2lnbmlmaWNhbnQgZGlmZmVyZW50aWFsbHkgZXhwcmVzc2VkIHJlc3VsdHM6IAoKCmBgYHtyfQojRW5yaWNobWVudCBhbmFseXNpcyAKZ29zdHJlc19rc2VhIDwtIGdvc3QocXVlcnkgPSBraW5hc2VfZW50cmV6X2lkc19pbmRpdmlkdWFsJEVOVFJFWklELCAKICAgICAgICAgICAgICAgIG9yZ2FuaXNtID0gImhzYXBpZW5zIiwgCiAgICAgICAgICAgICAgICBzb3VyY2VzID0gYygiR086QlAiLCAiR086TUYiLCAiR086Q0MiLCAiS0VHRyIsICJSRUFDIiwgIldQIiksIAogICAgICAgICAgICAgICAgc2lnbmlmaWNhbnQgPSBUUlVFLCAKICAgICAgICAgICAgICAgIGNvcnJlY3Rpb25fbWV0aG9kID0gImZkciIsICAKICAgICAgICAgICAgICAgIHVzZXJfdGhyZXNob2xkID0gMC4wNSkKCiNWaWV3IHJlc3VsdHMKaGVhZChnb3N0cmVzX2tzZWEkcmVzdWx0KQoKI1Bsb3QgCmdvc3RwbG90KGdvc3RyZXNfa3NlYSwgY2FwcGVkID0gVFJVRSwgaW50ZXJhY3RpdmUgPSBGQUxTRSkKYGBgCgpgYGB7cn0KCiMgUGxvdCBmb3IgZWFjaCBjYXRlZ29yeSAoR08sIEtFR0csIFJFQUNUT01FLCBXSUtJUEFUSFdBWVMpCmJwX3Bsb3Rfa3NlYSA8LSBwbG90X3Jlc3VsdHMoZ29zdHJlc19rc2VhJHJlc3VsdCwgIkdPOkJQIiwgIlRvcCBCaW9sb2dpY2FsIFByb2Nlc3NlcyIpCm1mX3Bsb3Rfa3NlYSA8LSBwbG90X3Jlc3VsdHMoZ29zdHJlc19rc2VhJHJlc3VsdCwgIkdPOk1GIiwgIlRvcCBNb2xlY3VsYXIgRnVuY3Rpb25zIikKY2NfcGxvdF9rc2VhIDwtIHBsb3RfcmVzdWx0cyhnb3N0cmVzX2tzZWEkcmVzdWx0LCAiR086Q0MiLCAiVG9wIENlbGx1bGFyIENvbXBvbmVudHMiKQpyZWFjX3Bsb3Rfa3NlYSA8LSBwbG90X3Jlc3VsdHMoZ29zdHJlc19rc2VhJHJlc3VsdCwgIlJFQUMiLCAiVG9wIFJlYWN0b21lIFBhdGh3YXlzIikKa2VnZ19wbG90X2tzZWEgPC0gcGxvdF9yZXN1bHRzKGdvc3RyZXNfa3NlYSRyZXN1bHQsICJLRUdHIiwgIlRvcCBLRUdHIFBhdGh3YXlzIikKd3BfcGxvdF9rc2VhIDwtIHBsb3RfcmVzdWx0cyhnb3N0cmVzX2tzZWEkcmVzdWx0LCAiV1AiLCAiVG9wIFdpa2lQYXRod2F5cyIpCgojIFByaW50IHBsb3RzCnByaW50KGJwX3Bsb3Rfa3NlYSkKcHJpbnQobWZfcGxvdF9rc2VhKQpwcmludChjY19wbG90X2tzZWEpCnByaW50KHJlYWNfcGxvdF9rc2VhKQpwcmludChrZWdnX3Bsb3Rfa3NlYSkgIApwcmludCh3cF9wbG90X2tzZWEpICAKYGBgCgoKUk5BIGRhdGE6CgpgYGB7cn0KI0ZpbHRlciBmb3Igc2FtcGxlcyB0aGF0IGV4aXN0IGluIHRoZSBSTkEgZGF0YXNldAoKcm5hX3Nob3J0X3NhbXBsZXMgPC0gaW50ZXJzZWN0KHNob3J0X3NhbXBsZXMsIGNvbG5hbWVzKHJuYV9kYXRhKSkKcm5hX2xvbmdfc2FtcGxlcyA8LSBpbnRlcnNlY3QobG9uZ19zYW1wbGVzLCBjb2xuYW1lcyhybmFfZGF0YSkpCgpybmFfZmlsdGVyZWQgPC0gcm5hX2RhdGEgJT4lCiAgZHBseXI6OnNlbGVjdChYLCBhbGxfb2Yocm5hX3Nob3J0X3NhbXBsZXMpLCBhbGxfb2Yocm5hX2xvbmdfc2FtcGxlcykpCgpkaW0ocm5hX2ZpbHRlcmVkKQoKYGBgCgpQcmUtcHJvY2Vzc2luZyBzdGVwczogCgpgYGB7cn0KI2NvbnZlcnQgZGF0YSB0byBERVNlcTIgZm9ybWF0CmRkcyA8LSBERVNlcURhdGFTZXRGcm9tTWF0cml4KGNvdW50RGF0YSA9IGFzLm1hdHJpeChybmFfZmlsdGVyZWRbLCAtMV0pLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sRGF0YSA9IGRhdGEuZnJhbWUoY29uZGl0aW9uID0gZmFjdG9yKGMocmVwKCJzaG9ydCIsIGxlbmd0aChybmFfc2hvcnRfc2FtcGxlcykpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlcCgibG9uZyIsIGxlbmd0aChybmFfbG9uZ19zYW1wbGVzKSkpKSksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZXNpZ24gPSB+IGNvbmRpdGlvbikKCgojQXNzaWduIHJvd25hbWVzIHRvIGRkcyBvYmplY3QKcm93bmFtZXMoZGRzKSA8LSBybmFfZmlsdGVyZWQkWAoKI0ZpbHRlciBvdXQgbG93IGNvdW50IGdlbmVzCmtlZXAgPC0gcm93U3Vtcyhjb3VudHMoZGRzKSA+PSAxMCkgPj0gMwpkZHMgPC0gZGRzW2tlZXAsXQoKIyBSdW4gREVTZXEyIHRvIG5vcm1hbGl6ZSB0aGUgZGF0YQpkZHMgPC0gREVTZXEoZGRzKQpub3JtYWxpemVkX2NvdW50cyA8LSBjb3VudHMoZGRzLCBub3JtYWxpemVkID0gVFJVRSkKCiNMb2cyIHRyYW5zZm9ybSB0aGUgbm9ybWFsaXplZCBjb3VudHMKbG9nMl9ub3JtYWxpemVkX2NvdW50cyA8LSBsb2cyKG5vcm1hbGl6ZWRfY291bnRzICsgMSkKCiNTY2FsZSBhbmQgY2VudHJlCnNjYWxlZF9jb3VudHMgPC0gc2NhbGUobG9nMl9ub3JtYWxpemVkX2NvdW50cywgY2VudGVyID0gVFJVRSwgc2NhbGUgPSBUUlVFKSAKCiMgQ29udmVydCBiYWNrIHRvIGEgZGF0YSBmcmFtZSBmb3IgZWFzeS9iZXR0ZXIgaGFuZGxpbmcKc2NhbGVkX2NvdW50c19kZiA8LSBhcy5kYXRhLmZyYW1lKHNjYWxlZF9jb3VudHMpCgojIFVwZGF0ZSBnZW5lIGlkZW50aWZpZXJzIGlmIHRoZXkgd2VyZSBpbiByb3duYW1lcwpyb3duYW1lcyhzY2FsZWRfY291bnRzX2RmKSA8LSByb3duYW1lcyhsb2cyX25vcm1hbGl6ZWRfY291bnRzKQoKI25ldyBkYXRhIGZyYW1lIC0gY29tYmluZWQgCnJuYV9zY2FsZWRfZmluYWwgPC0gZGF0YS5mcmFtZShnZW5lID0gcm93bmFtZXMoc2NhbGVkX2NvdW50c19kZiksIHNjYWxlZF9jb3VudHNfZGYpCgoKCmBgYAoKYGBge3J9CiMgQm94cGxvdCB0byB2aXN1YWxpemUgdGhlIGRhdGEgZGlzdHJpYnV0aW9uIChiZWZvcmUgYW5kIGFmdGVyKQoKIyBCZWZvcmUKYm94cGxvdChybmFfZmlsdGVyZWRbLCAtMV0sIGxhcyA9IDMsIG1haW4gPSAiUk5BLXNlcSBEYXRhIERpc3RyaWJ1dGlvbiBiZWZvcmUgUHJlcHJvY2Vzc2luZyIsIGNleC5tYWluID0gMikKCiNBZnRlcgpib3hwbG90KHJuYV9zY2FsZWRfZmluYWxbLCAtMV0sIGxhcyA9IDMsIG1haW4gPSAiUk5BLXNlcSBEYXRhIERpc3RyaWJ1dGlvbiBhZnRlciBQcmVwcm9jZXNzaW5nIHN0ZXBzIiwgY2V4Lm1haW4gPSAyKQoKCmBgYAoKRGlmZmVyZW50aWFsIGV4cHJlc3Npb24gYW5hbHlzaXM6CgpgYGB7cn0KCiMgUGVyZm9ybSBkaWZmZXJlbnRpYWwgYW5hbHlzaXMKZGYubGltbWEucm5hIDwtIGNvbXBhcmUuYnkubGltbWEocm5hX3NjYWxlZF9maW5hbCwgcm5hX2xvbmdfc2FtcGxlcywgcm5hX3Nob3J0X3NhbXBsZXMpCgojIEZpbHRlciBzaWduaWZpY2FudCByZXN1bHRzIGJhc2VkIG9uIHAtdmFsdWUKc2lnbmlmaWNhbnRfcm5hX3Jlc3VsdHMgPC0gZGYubGltbWEucm5hW2RmLmxpbW1hLnJuYSRwdmFsdWVzIDwgcF92YWx1ZV90aHJlc2hvbGQsIF0KCgojVmlldyBhbGwgc2lnbmlmaWNhbnQgcmVzdWx0cwpwcmludChzaWduaWZpY2FudF9ybmFfcmVzdWx0cykKCiMgT3JkZXIgdGhlIHNpZ25pZmljYW50IHJlc3VsdHMgYnkgYWJzb2x1dGUgZGlmZmVyZW50aWFsIGV4cHJlc3Npb24gLyBtb3N0IGV4cHJlc3NlZCBidXQgYWxzbyBwdmFsdWUgPDAuMDUgCnNpZ25pZmljYW50X3JuYV9yZXMgPC0gc2lnbmlmaWNhbnRfcm5hX3Jlc3VsdHNbb3JkZXIoYWJzKHNpZ25pZmljYW50X3JuYV9yZXN1bHRzJGRpZmZlcmVuY2UubG9uZy52cy5zaG9ydCksIGRlY3JlYXNpbmcgPSBUUlVFKSwgXQoKIyBWaWV3IHRoZSB0b3AgMTAgbW9zdCBzaWduaWZpY2FudCBoaXRzCnRvcF9zaWduaWZpY2FudF9ybmEgPC0gaGVhZChzaWduaWZpY2FudF9ybmFfcmVzLCAyMCkgIAojUHJpbnQgdG9wIDEwCnByaW50KHRvcF9zaWduaWZpY2FudF9ybmEpCgpgYGAKCgpgYGB7cn0KIyB2b2xjYW5vIHBsb3QgZm9yIGRpZmZlcmVudGlhbCBleHByZXNzaW9uIHJlc3VsdHMgCgpnZ3Bsb3QoZGYubGltbWEucm5hLCBhZXMoeCA9IGRpZmZlcmVuY2UubG9uZy52cy5zaG9ydCwgeSA9IC1sb2cxMChwdmFsdWVzKSkpICsKICAgIGdlb21fcG9pbnQoYWVzKGNvbG9yID0gcHZhbHVlcyA8IHB2YWxfdGhyZXNob2xkKSkgKwogICAgdGhlbWVfbWluaW1hbCgpICsKICAgIGxhYnModGl0bGUgPSAiVm9sY2FubyBQbG90IGZvciBSTkEgRGF0YSIsIAogICAgICAgICB4ID0gIkxvZzIgRm9sZCBDaGFuZ2UiLCAKICAgICAgICAgeSA9ICItbG9nMTAocC12YWx1ZSkiKSArCiAgICBnZW9tX3RleHRfcmVwZWwoZGF0YSA9IHRvcF9zaWduaWZpY2FudF9ybmEsICNkaXNwbGF5ZWQgYXJlIHRoZSB0b3AgMjAgaW5zdGVhZCBvZiAxMCB0aGlzIHRpbWUsIHRvIGFsc28gaGF2ZSBhIGZlYXR1cmUgdXByZWd1bGF0ZWQgaW4gdGhlIHNob3J0IHN1cnZpdmFsIHNpZGUgCiAgICAgICAgICAgICAgICAgICAgYWVzKGxhYmVsID0gWCksCiAgICAgICAgICAgICAgICAgICAgc2l6ZSA9IDMsIAogICAgICAgICAgICAgICAgICAgIG1heC5vdmVybGFwcyA9IEluZikgKyAgIyBVc2UgSW5mIHRvIGF2b2lkIGZpbHRlcmluZyBvdXQgdG9wIDUKICAgIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjKCJyZWQiLCAiYmx1ZSIpLCBuYW1lID0gInB2YWx1ZXMgPCAwLjA1IikgKwogICAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gInJpZ2h0IikKYGBgCgpQQVRIV0FZIEVOUklDSE1FTlQgQU5BTFlTSVMKCkdPIEVucmljaG1lbnQ6CgpgYGB7cn0KI0V4dHJhY3Qgc2lnbmlmaWNhbnQgZ2VuZXMgCmdlbmVfbGlzdF9ybmEgPC0gc2lnbmlmaWNhbnRfcm5hX3Jlc3VsdHMkWAoKI3JlbW92ZSBldmVyeXRoaW5nIGFmdGVyIHRoZSBkb3QKI3RoZSBwcmVzZW5jZSBvZiBhZGRpdGlvbmFsIHN1ZmZpeGVzIG9yIG5vbi1zdGFuZGFyZCBmb3JtYXRzIGluIHRoZSBnZW5lIG5hbWVzLCBzdWNoIGFzIHRoZSB1c2Ugb2YgZG90cyAoZS5nLiwgQUMwNzMwNzIuMSBvciBFQUYxLkFTMSkuIFRoZXNlIHN5bWJvbHMgbWlnaHQgcmVwcmVzZW50IGRpZmZlcmVudCBpc29mb3JtcywgdHJhbnNjcmlwdCB2YXJpYW50cywgb3Igb3RoZXIgbm9uLWNhbm9uaWNhbCBpZGVudGlmaWVycyB0aGF0IGFyZW4ndCBkaXJlY3RseSByZWNvZ25pemVkIGluIHRoZSBvcmcuSHMuZWcuZGIgZGF0YWJhc2UgZm9yIEVudHJleiBJRCBjb252ZXJzaW9uLiAtIHNvIHJlbW92ZWQgdG8ga2VlcCBhIGNsZWFuIGRhdGEgZm9yIHBhdGh3YXkgZW5yaWNobWVudCAKZ2VuZV9saXN0X3JuYV9jbGVhbmVkIDwtIGdzdWIoIlxcLi4qIiwgIiIsIGdlbmVfbGlzdF9ybmEpCgojQ29udmVydCBnZW5lIHN5bWJvbHMgdG8gRW50cmV6IElEcwplbnRyZXpfaWRzX3JuYSA8LSBiaXRyKGdlbmVfbGlzdF9ybmFfY2xlYW5lZCwgZnJvbVR5cGUgPSAiU1lNQk9MIiwgdG9UeXBlID0gIkVOVFJFWklEIiwgT3JnRGIgPSBvcmcuSHMuZWcuZGIpCgojNi41NyUgb2YgaW5wdXQgZ2VuZSBJRHMgYXJlIGZhaWwgdG8gbWFwLi4uCmBgYAoKYGBge3J9CiNHTyBlbnJpY2htZW50IAoKI3VzZWQgdW5hZGp1c3RlZCBwdmFsdWUsIGJ1dCBzdGlsbCBubyByZXN1bHRzCmdvX1JOQV9lbnJpY2htZW50IDwtIGVucmljaEdPKGdlbmUgPSBlbnRyZXpfaWRzX3JuYSRFTlRSRVpJRCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgT3JnRGIgPSBvcmcuSHMuZWcuZGIsIAogICAgICAgICAgICAgICAgICAgICAgICAgIG9udCA9ICJCUCIsICMgIkJQIiBmb3IgQmlvbG9naWNhbCBQcm9jZXNzZXMKICAgICAgICAgICAgICAgICAgICAgICAgICBwQWRqdXN0TWV0aG9kID0gIm5vbmUiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICBwdmFsdWVDdXRvZmYgPSAwLjA1LCAKICAgICAgICAgICAgICAgICAgICAgICAgICBxdmFsdWVDdXRvZmYgPSAwLjIsIAogICAgICAgICAgICAgICAgICAgICAgICAgIHJlYWRhYmxlID0gVFJVRSkKCgojIG90aGVyIGNhdGVnb3JpZXMgKE1GLCBDQykKCiN1c2VkIHVuYWRqdXN0ZWQgcHZhbHVlLCBidXQgc3RpbGwgbm8gcmVzdWx0cwpnb19lbnJpY2htZW50X1JOQV9NRiA8LSBlbnJpY2hHTyhnZW5lID0gZW50cmV6X2lkc19ybmEkRU5UUkVaSUQsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIE9yZ0RiID0gb3JnLkhzLmVnLmRiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvbnQgPSAiTUYiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwQWRqdXN0TWV0aG9kID0gIm5vbmUiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwdmFsdWVDdXRvZmYgPSAwLjA1LCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBxdmFsdWVDdXRvZmYgPSAwLjIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlYWRhYmxlID0gVFJVRSkKCiNyZXN1bHRzIGNyZWF0ZWQgCmdvX2VucmljaG1lbnRfUk5BX0NDIDwtIGVucmljaEdPKGdlbmUgPSBlbnRyZXpfaWRzX3JuYSRFTlRSRVpJRCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgT3JnRGIgPSBvcmcuSHMuZWcuZGIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9udCA9ICJDQyIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBBZGp1c3RNZXRob2QgPSAiQkgiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwdmFsdWVDdXRvZmYgPSAwLjA1LCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBxdmFsdWVDdXRvZmYgPSAwLjIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlYWRhYmxlID0gVFJVRSkKCgoKYGBgCgoKCmBgYHtyfQojIFZpc3VhbGl6ZSBDQwoKZG90cGxvdChnb19lbnJpY2htZW50X1JOQV9DQywgc2hvd0NhdGVnb3J5ID0gMTAsIHRpdGxlID0gIkdPIENlbGx1bGFyIENvbXBvbmVudHMgRW5yaWNobWVudCIpCmBgYAoKCkZvciBzcGVjaWZpY2FsbHkgYmFkLXJlc3BvbmRlcnMvIHRhcmdldHMgYXNzb2NpYXRlZCB3aXRoIHNob3J0IHN1cnZpdmFsIGdyb3VwOgoKYGBge3J9CiNGaWx0ZXIvc3Vic2V0IGRhdGEsIGtlZXBpbmcgb25seSBmZWF0dXJlcyB1cHJlZ3VsYXRlZCBpbiB0aGUgc2hvcnQgc3Vydml2YWwgZ3JvdXAgCnN1YnNldF9ybmEgPC0gc3Vic2V0KHNpZ25pZmljYW50X3JuYV9yZXN1bHRzLCBkaWZmZXJlbmNlLmxvbmcudnMuc2hvcnQgPiAwKQpzdWJzZXRfcm5hIDwtIHN1YnNldF9ybmEkWAojY2xlYW4gLSByZWFkeSBmb3IgYW5hbHlzaXMgCnN1YnNldF9ybmFfY2xlYW5lZCA8LSBnc3ViKCJcXC4uKiIsICIiLCBzdWJzZXRfcm5hKQoKIyBDb252ZXJ0IHRoZXNlIGtpbmFzZSBuYW1lcyB0byBFbnRyZXogSURzCmVuX2lkc19ybmEgPC0gYml0cihzdWJzZXRfcm5hX2NsZWFuZWQsIGZyb21UeXBlID0gIlNZTUJPTCIsIHRvVHlwZSA9ICJFTlRSRVpJRCIsIE9yZ0RiID0gb3JnLkhzLmVnLmRiKQoKI0dPIGVucmljaG1lbnQgCmdvX3JuYV9wX2VucmljaG1lbnQgPC0gZW5yaWNoR08oZ2VuZSA9IGVuX2lkc19ybmEkRU5UUkVaSUQsIAogICAgICAgICAgICAgICAgICAgICAgICAgIE9yZ0RiID0gb3JnLkhzLmVnLmRiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICBvbnQgPSAiQlAiLCAjICJCUCIgZm9yIEJpb2xvZ2ljYWwgUHJvY2Vzc2VzCiAgICAgICAgICAgICAgICAgICAgICAgICAgcEFkanVzdE1ldGhvZCA9ICJCSCIsIAogICAgICAgICAgICAgICAgICAgICAgICAgIHB2YWx1ZUN1dG9mZiA9IDAuMDUsIAogICAgICAgICAgICAgICAgICAgICAgICAgIHF2YWx1ZUN1dG9mZiA9IDAuMiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgcmVhZGFibGUgPSBUUlVFKQoKCiNQbG90cwpiYXJwbG90KGdvX3JuYV9wX2VucmljaG1lbnQsIHNob3dDYXRlZ29yeSA9IDEwLCB0aXRsZSA9ICJHTyBCaW9sb2dpY2FsIFByb2Nlc3NlcyBlbnJpY2hlZCBpbiBzaG9ydCBzdXJ2aXZhbCBncm91cCIpCmRvdHBsb3QoZ29fcm5hX3BfZW5yaWNobWVudCwgc2hvd0NhdGVnb3J5ID0gMTAsIHRpdGxlID0gIkdPIEJpb2xvZ2ljYWwgUHJvY2Vzc2VzIGVucmljaGVkIGluIHNob3J0IHN1cnZpdmFsIGdyb3VwIikKaGVhdHBsb3QoZ29fcm5hX3BfZW5yaWNobWVudCwgc2hvd0NhdGVnb3J5ID0gMTApCgoKI25ldHdvcmsgcGxvdCAKY25ldHBsb3QoZ29fcm5hX3BfZW5yaWNobWVudCwgc2hvd0NhdGVnb3J5ID0gNSwgdGl0bGUgPSAiR2VuZS1Db25jZXB0IE5ldHdvcmsgZm9yIEJpb2xvZ2ljYWwgUHJvY2Vzc2VzIGVucmljaGVkIGluIHNob3J0IHN1cnZpdmFsIGdyb3VwIiwgCiAgICAgICAgIG1heC5vdmVybGFwcyA9IDEwMCwgbm9kZV9sYWJlbF9zaXplID0gMywgbGFiZWxfZm9udHNpemUgPSA4KSArCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwKSwgCiAgICAgICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwKSwgCiAgICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTQsIGZhY2UgPSAiYm9sZCIpKQoKI2RlY2lkZWQgb24gNSB0byBub3Qgb3ZlcndoZWxtIHRoZSBwbG90IApgYGAKCgoKVXNpbmcgZ3Byb2ZpbGVyMiAvIGZvciBhbGwgc2lnbmlmaWNhbnQgZGlmZmVyZW50aWFsbHkgZXhwcmVzc2VkIGZlYXR1cmVzIAoKCmBgYHtyfQoKZ29zdHJlc19STkEgPC0gZ29zdChxdWVyeSA9IGVudHJlel9pZHNfcm5hJEVOVFJFWklELCAKICAgICAgICAgICAgICAgIG9yZ2FuaXNtID0gImhzYXBpZW5zIiwgCiAgICAgICAgICAgICAgICBzb3VyY2VzID0gYygiR086QlAiLCAiR086TUYiLCAiR086Q0MiLCAiS0VHRyIsICJSRUFDIiwgIldQIiksIAogICAgICAgICAgICAgICAgc2lnbmlmaWNhbnQgPSBUUlVFLCAKICAgICAgICAgICAgICAgIGNvcnJlY3Rpb25fbWV0aG9kID0gImZkciIsICAKICAgICAgICAgICAgICAgIHVzZXJfdGhyZXNob2xkID0gMC4wNSkKCiMgVmlldyByZXN1bHRzCmhlYWQoZ29zdHJlc19STkEkcmVzdWx0KQoKIyBQbG90IApnb3N0cGxvdChnb3N0cmVzX1JOQSwgY2FwcGVkID0gVFJVRSwgaW50ZXJhY3RpdmUgPSBGQUxTRSkKYGBgCgoKYGBge3J9CgojIFBsb3QgZm9yIGVhY2ggY2F0ZWdvcnkgKEdPLCBLRUdHLCBSRUFDVE9NRSwgV0lLSVBBVEhXQVlTKQpicF9wbG90X1JOQSA8LSBwbG90X3Jlc3VsdHMoZ29zdHJlc19STkEkcmVzdWx0LCAiR086QlAiLCAiVG9wIEJpb2xvZ2ljYWwgUHJvY2Vzc2VzIikKbWZfcGxvdF9STkEgPC0gcGxvdF9yZXN1bHRzKGdvc3RyZXNfUk5BJHJlc3VsdCwgIkdPOk1GIiwgIlRvcCBNb2xlY3VsYXIgRnVuY3Rpb25zIikKY2NfcGxvdF9STkEgPC0gcGxvdF9yZXN1bHRzKGdvc3RyZXNfUk5BJHJlc3VsdCwgIkdPOkNDIiwgIlRvcCBDZWxsdWxhciBDb21wb25lbnRzIikKcmVhY19wbG90X1JOQSA8LSBwbG90X3Jlc3VsdHMoZ29zdHJlc19STkEkcmVzdWx0LCAiUkVBQyIsICJUb3AgUmVhY3RvbWUgUGF0aHdheXMiKQprZWdnX3Bsb3RfUk5BIDwtIHBsb3RfcmVzdWx0cyhnb3N0cmVzX1JOQSRyZXN1bHQsICJLRUdHIiwgIlRvcCBLRUdHIFBhdGh3YXlzIikKd3BfcGxvdF9STkEgPC0gcGxvdF9yZXN1bHRzKGdvc3RyZXNfUk5BJHJlc3VsdCwgIldQIiwgIlRvcCBXaWtpUGF0aHdheXMiKQoKIyBQcmludCBwbG90cwpwcmludChicF9wbG90X1JOQSkKcHJpbnQobWZfcGxvdF9STkEpCnByaW50KGNjX3Bsb3RfUk5BKQpwcmludChyZWFjX3Bsb3RfUk5BKSAjTm8gcmVhY3RvbWUKcHJpbnQoa2VnZ19wbG90X1JOQSkgICNObyBLRUdHCnByaW50KHdwX3Bsb3RfUk5BKSAgI05vIFdpa2lQYXRod2F5cyAKYGBgCgoKCk5PVyBGVVJUSEVSIEFOQUxZWkUgUEFUSUVOVCBJTkZPUk1BVElPTiAKRklORCBTT01FIERFU0NSSVBUSVZFIFNUQVRJU1RJQ1MsIFBBVElFTlQgREVNT0dSQVBISUMgSU5GT1JNQVRJT046IAoKYGBge3J9CgojQ0hFQ0sgUEFUSUVOVCBJTkZPIC8gS0FSWU9UWVBFUyAKcHRfc2hvcnQgPC0gaW50ZXJzZWN0KHNob3J0X3NhbXBsZXMsIHB0X2luZm8kU2FtcGxlX05hbWUpCnB0X2xvbmcgPC0gaW50ZXJzZWN0KGxvbmdfc2FtcGxlcywgcHRfaW5mbyRTYW1wbGVfTmFtZSkKCiNGaWx0ZXIgaW4gZWFjaCBncm91cCBmb3IgdGhlIGluZm9ybWF0aW9uIEkgYW0gaW50ZXJlc3RlZCBpbiB3aGljaCBpczogYW1wbGVfTmFtZSwgVHlwZSwgR2VuZGVyLCBEaXNlYXNlLCBTdGFnZSwgS2FyeW90eXBlLCBLYXJ5b3R5cGVfZ3JvdXAsIGFnZS5hdC5kaWFnbm9zaXMsIFNUQVRVUywgU1VSVklWQUwuLllSUy4KCnB0X2luZm9fc2hvcnQgPC0gcHRfaW5mbyAlPiUKICBmaWx0ZXIoU2FtcGxlX05hbWUgJWluJSBwdF9zaG9ydCkgJT4lCiAgZHBseXI6OnNlbGVjdChTYW1wbGVfTmFtZSwgVHlwZSwgR2VuZGVyLCBEaXNlYXNlLCBTdGFnZSwgS2FyeW90eXBlLCBLYXJ5b3R5cGVfZ3JvdXAsIGFnZS5hdC5kaWFnbm9zaXMsIFNUQVRVUywgU1VSVklWQUwuLllSUy4pCgoKcHRfaW5mb19sb25nIDwtIHB0X2luZm8gJT4lCiAgZmlsdGVyKFNhbXBsZV9OYW1lICVpbiUgcHRfbG9uZykgJT4lCiAgZHBseXI6OnNlbGVjdChTYW1wbGVfTmFtZSwgVHlwZSwgR2VuZGVyLCBEaXNlYXNlLCBTdGFnZSwgS2FyeW90eXBlLCBLYXJ5b3R5cGVfZ3JvdXAsIGFnZS5hdC5kaWFnbm9zaXMsIFNUQVRVUywgU1VSVklWQUwuLllSUy4pCgojUHJpbnQgdG8gdmlldyAKcHJpbnQocHRfaW5mb19zaG9ydCkKcHJpbnQocHRfaW5mb19sb25nKQoKYGBgCgpJbiB0ZXJtcyBvZiBwYXRpZW50IGRlbW9ncmFwaGljcyBjaGVjayB0aGUgYWdlIGFuZCBnZW5kZXI6IAoKQUdFIEFORCBHRU5ERVIgCmBgYHtyfQojRW5zdXJlIGFsbCB2YWx1ZXMgYXJlIG51bWVyaWMgLyBhcyB0aGVyZSBhcmUgc29tZSBtaXNzaW5nIHZhbHVlcyBpbiB0aGVzZSBkYXRhc2V0cyAKcHRfaW5mb19zaG9ydCRhZ2UuYXQuZGlhZ25vc2lzIDwtIGFzLm51bWVyaWMoYXMuY2hhcmFjdGVyKHB0X2luZm9fc2hvcnQkYWdlLmF0LmRpYWdub3NpcykpCnB0X2luZm9fbG9uZyRhZ2UuYXQuZGlhZ25vc2lzIDwtIGFzLm51bWVyaWMoYXMuY2hhcmFjdGVyKHB0X2luZm9fbG9uZyRhZ2UuYXQuZGlhZ25vc2lzKSkKCiNjYWxjdWxhdGUgbWVhbiBhZ2UKbWVhbl9hZ2Vfc2hvcnQgPC0gbWVhbihwdF9pbmZvX3Nob3J0JGFnZS5hdC5kaWFnbm9zaXMsIG5hLnJtID0gVFJVRSkgI25hLnJtIGFzIHRoZXJlIGFyZSBzb21lIG1pc3NpbmcgdmFsdWVzIGluIHRoZXNlIGRhdGFzZXRzIAptZWFuX2FnZV9sb25nIDwtIG1lYW4ocHRfaW5mb19sb25nJGFnZS5hdC5kaWFnbm9zaXMsIG5hLnJtID0gVFJVRSkKCiNDYWxjdWxhdGUgZ2VuZGVyIG92ZXJhbGwgbnVtYmVyIGZvciB0aGUgc2hvcnQgc3Vydml2YWwgZ3JvdXAKZ2VuZGVyX2NvdW50X3Nob3J0IDwtIHB0X2luZm9fc2hvcnQgJT4lCiAgZ3JvdXBfYnkoR2VuZGVyKSAlPiUKICBzdW1tYXJpemUoQ291bnQgPSBuKCkpCgojQ2FsY3VsYXRlIGdlbmRlciBvdmVyYWxsIG51bWJlciBmb3IgdGhlIGxvbmcgc3Vydml2YWwgZ3JvdXAKZ2VuZGVyX2NvdW50X2xvbmcgPC0gcHRfaW5mb19sb25nICU+JQogIGdyb3VwX2J5KEdlbmRlcikgJT4lCiAgc3VtbWFyaXplKENvdW50ID0gbigpKQoKIyBQcmludCByZXN1bHRzCiNzaG9ydApjYXQoIk1lYW4gQWdlOiIsIG1lYW5fYWdlX3Nob3J0LCAiXG4iKQpwcmludChnZW5kZXJfY291bnRfc2hvcnQpCgojbG9uZyAKY2F0KCJNZWFuIEFnZToiLCBtZWFuX2FnZV9sb25nLCAiXG4iKQpwcmludChnZW5kZXJfY291bnRfbG9uZykKCgpgYGAKCktBUllPVFlQRSBHUk9VUDoKVGhlc2UgZGlmZmVyZW50IHR5cGVzIGFyZSBmb3VuZCBpbiB0aGVzZSBwYXRpZW50czogIk1MTCIsICJDb21wbGV4IiwgImRlbDE3IiwgImRlbDUiLCAiZGVsNyIsICJ0KDM7MykiLCAidCg4OzE2KSIKYGBge3J9CiMgQ2FsY3VsYXRlIHRoZSBjb3VudCBvZiBlYWNoIGthcnlvdHlwZSBncm91cCAtIHNob3J0IHN1cnZpdmFsIGdyb3VwCmthcnlvdHlwZV9jb3VudF9zaG9ydCA8LSBwdF9pbmZvX3Nob3J0ICU+JQogIGZpbHRlcihLYXJ5b3R5cGVfZ3JvdXAgJWluJSBjKCJNTEwiLCAiQ29tcGxleCIsICJkZWwxNyIsICJkZWw1IiwgImRlbDciLCAidCgzOzMpIiwgInQoODsxNikiKSkgJT4lCiAgZ3JvdXBfYnkoS2FyeW90eXBlX2dyb3VwKSAlPiUKICBzdW1tYXJpemUoQ291bnQgPSBuKCkpCgojIHRoZSBzYW1lIGZvciB0aGUgbG9uZyBzdXJ2aXZhbCBncm91cAprYXJ5b3R5cGVfY291bnRfbG9uZyA8LSBwdF9pbmZvX2xvbmcgJT4lCiAgZmlsdGVyKEthcnlvdHlwZV9ncm91cCAlaW4lIGMoIk1MTCIsICJDb21wbGV4IiwgImRlbDE3IiwgImRlbDUiLCAiZGVsNyIsICJ0KDM7MykiLCAidCg4OzE2KSIpKSAlPiUKICBncm91cF9ieShLYXJ5b3R5cGVfZ3JvdXApICU+JQogIHN1bW1hcml6ZShDb3VudCA9IG4oKSkKCiMgUHJpbnQgcmVzdWx0cwojc2hvcnQKcHJpbnQoa2FyeW90eXBlX2NvdW50X3Nob3J0KQoKI2xvbmcKcHJpbnQoa2FyeW90eXBlX2NvdW50X2xvbmcpCgpgYGAKCgpTb21lIGRlc2NyaXB0aXZlIHN0YXRpc3RpY3MgcmVnYXJkaW5nIHRoZSBwYXRpZW50cycgc3Vydml2YWwgeWVhcnMgLSBvdmVyYWxsIGFuZCB0aGUgdHdvIGdyb3VwczogCgoKYGBge3J9CiNkZXNjcmlwdGl2ZSBzdGF0aXN0aWNzIGZvciB0aGUgd2hvbGUgZGF0YXNldCAoYWxsIHBhdGllbnRzKSAtIG1pbmltdW0gdmFsdWUsIG1heCwgbWVkaWFuIHN1cnZpdmFsLCBhbmQgcmFuZ2UgCgojY2FsY3VsYXRlIGFsbCAKb3ZlcmFsbF9zdXJ2aXZhbF9zdGF0cyA8LSBwYXRpZW50c19saXN0ICU+JQogIHN1bW1hcmlzZSgKICAgIG1lYW5fc3Vydml2YWwgPSBtZWFuKGBTVVJWSVZBTC4uWVJTLmApLAogICAgbWVkaWFuX3N1cnZpdmFsID0gbWVkaWFuKGBTVVJWSVZBTC4uWVJTLmApLAogICAgbWluX3N1cnZpdmFsID0gbWluKGBTVVJWSVZBTC4uWVJTLmApLAogICAgbWF4X3N1cnZpdmFsID0gbWF4KGBTVVJWSVZBTC4uWVJTLmApLAogICAgcmFuZ2Vfc3Vydml2YWwgPSBtYXgoYFNVUlZJVkFMLi5ZUlMuYCkgLSBtaW4oYFNVUlZJVkFMLi5ZUlMuYCkKICApCgoKIyBQcmludApwcmludChvdmVyYWxsX3N1cnZpdmFsX3N0YXRzKQoKYGBgCgpgYGB7cn0KI2Rlc2NyaXB0aXZlIHN0YXRpc3RpY3MgZm9yIHRoZSBzaG9ydCBzdXJ2aXZhbCBncm91cCAtIG1pbmltdW0gdmFsdWUsIG1heCwgbWVkaWFuIHN1cnZpdmFsLCBhbmQgcmFuZ2UgCgojY2FsY3VsYXRlIGFsbCAKc2hvcnRfc3Vydml2YWxfc3RhdHMgPC0gc2hvcnRfc3Vydml2YWxzICU+JQogIHN1bW1hcmlzZSgKICAgIG1lYW5fc3Vydml2YWwgPSBtZWFuKGBTVVJWSVZBTC4uWVJTLmApLAogICAgbWVkaWFuX3N1cnZpdmFsID0gbWVkaWFuKGBTVVJWSVZBTC4uWVJTLmApLAogICAgbWluX3N1cnZpdmFsID0gbWluKGBTVVJWSVZBTC4uWVJTLmApLAogICAgbWF4X3N1cnZpdmFsID0gbWF4KGBTVVJWSVZBTC4uWVJTLmApLAogICAgIHJhbmdlX3N1cnZpdmFsID0gbWF4KGBTVVJWSVZBTC4uWVJTLmApIC0gbWluKGBTVVJWSVZBTC4uWVJTLmApCiAgKQoKCiMgUHJpbnQKcHJpbnQoc2hvcnRfc3Vydml2YWxfc3RhdHMpCgpgYGAKCmBgYHtyfQojIGRlc2NyaXB0aXZlIHN0YXRpc3RpY3MgZm9yIHRoZSBsb25nIHN1cnZpdmFsIGdyb3VwIC1taW5pbXVtIHZhbHVlLCBtYXgsIG1lZGlhbiBzdXJ2aXZhbCwgYW5kIHJhbmdlIAoKI2NhbGN1bGF0ZSBhbGwKbG9uZ19zdXJ2aXZhbF9zdGF0cyA8LSBsb25nX3N1cnZpdmFscyAlPiUKICBzdW1tYXJpc2UoCiAgICBtZWFuX3N1cnZpdmFsID0gbWVhbihgU1VSVklWQUwuLllSUy5gKSwKICAgIG1lZGlhbl9zdXJ2aXZhbCA9IG1lZGlhbihgU1VSVklWQUwuLllSUy5gKSwKICAgIG1pbl9zdXJ2aXZhbCA9IG1pbihgU1VSVklWQUwuLllSUy5gKSwKICAgIG1heF9zdXJ2aXZhbCA9IG1heChgU1VSVklWQUwuLllSUy5gKSwgIAogICAgcmFuZ2Vfc3Vydml2YWwgPSBtYXgoYFNVUlZJVkFMLi5ZUlMuYCkgLSBtaW4oYFNVUlZJVkFMLi5ZUlMuYCkKICApCgojcHJpbnQKcHJpbnQobG9uZ19zdXJ2aXZhbF9zdGF0cykKCmBgYAoKQ29tYmluZSBub3cgYWxsIG9mIHRoZW0gaW50byBhIGRhdGFmcmFtZSB0byBjcmVhdGUgYSBncmFwaCB0byBjb21wYXJlIHRoZW0sIGVhY2ggc3RhdGlzdGljOiBtaW5pbXVtIHZhbHVlLCBtYXgsIG1lZGlhbiBzdXJ2aXZhbCwgYW5kIHJhbmdlIDogCgpgYGB7cn0KCiNjb21iaW5lIGFsbCBzdXJ2aXZhbCBzdGF0aXN0aWNzIGludG8gb25lIGRhdGFmcmFtZQpjb21iaW5lZF9zdGF0cyA8LSBkYXRhLmZyYW1lKAogIEdyb3VwID0gYygiT3ZlcmFsbCIsICJTaG9ydCIsICJMb25nIiksCiAgTWVhbl9TdXJ2aXZhbCA9IGMob3ZlcmFsbF9zdXJ2aXZhbF9zdGF0cyRtZWFuX3N1cnZpdmFsLCBzaG9ydF9zdXJ2aXZhbF9zdGF0cyRtZWFuX3N1cnZpdmFsLCBsb25nX3N1cnZpdmFsX3N0YXRzJG1lYW5fc3Vydml2YWwpLAogIE1lZGlhbl9TdXJ2aXZhbCA9IGMob3ZlcmFsbF9zdXJ2aXZhbF9zdGF0cyRtZWRpYW5fc3Vydml2YWwsIHNob3J0X3N1cnZpdmFsX3N0YXRzJG1lZGlhbl9zdXJ2aXZhbCwgbG9uZ19zdXJ2aXZhbF9zdGF0cyRtZWRpYW5fc3Vydml2YWwpLAogIE1pbl9TdXJ2aXZhbCA9IGMob3ZlcmFsbF9zdXJ2aXZhbF9zdGF0cyRtaW5fc3Vydml2YWwsIHNob3J0X3N1cnZpdmFsX3N0YXRzJG1pbl9zdXJ2aXZhbCwgbG9uZ19zdXJ2aXZhbF9zdGF0cyRtaW5fc3Vydml2YWwpLAogIE1heF9TdXJ2aXZhbCA9IGMob3ZlcmFsbF9zdXJ2aXZhbF9zdGF0cyRtYXhfc3Vydml2YWwsIHNob3J0X3N1cnZpdmFsX3N0YXRzJG1heF9zdXJ2aXZhbCwgbG9uZ19zdXJ2aXZhbF9zdGF0cyRtYXhfc3Vydml2YWwpLAogIFJhbmdlX1N1cnZpdmFsID0gYyhvdmVyYWxsX3N1cnZpdmFsX3N0YXRzJHJhbmdlX3N1cnZpdmFsLCBzaG9ydF9zdXJ2aXZhbF9zdGF0cyRyYW5nZV9zdXJ2aXZhbCwgbG9uZ19zdXJ2aXZhbF9zdGF0cyRyYW5nZV9zdXJ2aXZhbCkKKQoKI2NvbnZlcnQgZGF0YSB0byBsb25nIGZvcm1hdCAtIGhlbHBzIHdpdGggdGhlIHBsb3R0aW5nCmxvbmdfc3RhdHMgPC0gdGlkeXI6OnBpdm90X2xvbmdlcihjb21iaW5lZF9zdGF0cywgY29scyA9IC1Hcm91cCwgbmFtZXNfdG8gPSAiU3RhdGlzdGljIiwgdmFsdWVzX3RvID0gIlZhbHVlIikKCiNwbG90IHRvIHZpZXcgYW5kIGNvbXBhcmUgYWxsIAoKZ2dwbG90KGxvbmdfc3RhdHMsIGFlcyh4ID0gR3JvdXAsIHkgPSBWYWx1ZSwgZmlsbCA9IFN0YXRpc3RpYykpICsKICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IiwgcG9zaXRpb24gPSAiZG9kZ2UiKSArICAjIEVuc3VyZSB0aGUgKyBpcyBhdCB0aGUgZW5kIG9mIHRoaXMgbGluZQogIGxhYnModGl0bGUgPSAiQ29tcGFyaXNvbiBvZiBTdXJ2aXZhbCBTdGF0aXN0aWNzIEFjcm9zcyB0aGUgR3JvdXBzIiwKICAgICAgIHggPSAiR3JvdXAiLAogICAgICAgeSA9ICJTdXJ2aXZhbCAoWWVhcnMpIiwKICAgICAgIGZpbGwgPSAiU3RhdGlzdGljIikgKwogIHRoZW1lX21pbmltYWwoKSArCiAgc2NhbGVfZmlsbF9icmV3ZXIocGFsZXR0ZSA9ICJTZXQzIikKCgpgYGAKCk5vdywgc29tZSBhZGRpdGlvbmFsIGRlc2NyaXB0aXZlIHN0YXRpc3RpY3MgZm9yIGVhY2ggZGF0YXNldCAtIGJhc2VkIG9uIHRoZSBkaWZmZXJlbnRpYWwgZXhwcmVzc2lvbiBhbmFseXNpcyByZXN1bHRzOgotIG92ZXJhbGwgbnVtYmVyIG9mIGZlYXR1cmVzIAotIG92ZXJhbGwgbnVtYmVyIG9mIGZlYXR1cmVzIHVwcmVndWxhdGVkIGluIHRoZSBzaG9ydCBzdXJ2aXZhbCBncm91cCAKLSBvdmVyYWxsIG51bWJlciBvZiBmZWF0dXJlcyB1cHJlZ3VsYXRlZCBpbiB0aGUgbG9uZyBzdXJ2aXZhbCBncm91cAoKYGBge3J9CiMgVG90YWwgbnVtYmVyIG9mIGZlYXR1cmVzIGluIGVhY2ggZGF0YXNldCBiZWZvcmUgZmlsdGVyaW5nIGZvciBzaWduaWZpY2FuY2UgKHAtdmFsdWUgPDAuMDUpCnRvdGFsX3Bob3NwaG9wcm90ZWlucyA8LSBucm93KGRmLmxpbW1hLnBob3NwaG8pCnRvdGFsX3Bob3NwaG9yeWxhdGlvbl9zaXRlcyA8LSBucm93KGRmLmxpbW1hLnBwKQp0b3RhbF9wcm90ZWlucyA8LSBucm93KGRmLmxpbW1hLnF1YW50KQp0b3RhbF9rc2VhIDwtIG5yb3coZGYubGltbWEua3NlYSkKdG90YWxfcm5hIDwtIG5yb3coZGYubGltbWEucm5hKQoKYGBgCgoKYGBge3J9CiMgTnVtYmVyIG9mIHNpZ25pZmljYW50bHkgZGlmZmVyZW50aWFsbHkgZXhwcmVzc2VkIGFuZCBzdGF0aXN0aWNhbGx5IHNpZ25pZmljYW50IChwLXZhbHVlPDAuMDUpIGZlYXR1cmVzIApudW1fc2lnX3Bob3NwaG9wcm90ZWlucyA8LSBucm93KHNpZ25pZmljYW50X3Bob3NwaG9fcmVzdWx0cykKbnVtX3NpZ19waG9zcGhvcnlsYXRpb25fc2l0ZXMgPC0gbnJvdyhzaWduaWZpY2FudF9wcF9yZXN1bHRzKQpudW1fc2lnX3Byb3RlaW5zIDwtIG5yb3coc2lnbmlmaWNhbnRfcHFfcmVzdWx0cykKbnVtX3NpZ19rc2VhIDwtIG5yb3coc2lnbmlmaWNhbnRfa3NlYV9yZXN1bHRzKQpudW1fc2lnX3JuYSA8LSBucm93KHNpZ25pZmljYW50X3JuYV9yZXN1bHRzKQoKIyBOdW1iZXIgb2YgaW5jcmVhc2VkIChhYm92ZSAwIC0gc2hvcnQgc3Vydml2YWwgdXByZWd1bGF0ZWQpIGFuZCBkZWNyZWFzZWQgKGJlbG93IDAgLSBsb25nIHN1cnZpdmFsIHVwcmVndWxhdGlvbikgZmVhdHVyZXMKbnVtX2luY3JlYXNlZF9waG9zcGhvcHJvdGVpbnMgPC0gc3VtKHNpZ25pZmljYW50X3Bob3NwaG9fcmVzdWx0cyRkaWZmZXJlbmNlLmxvbmcudnMuc2hvcnQgPiAwKQpudW1fZGVjcmVhc2VkX3Bob3NwaG9wcm90ZWlucyA8LSBzdW0oc2lnbmlmaWNhbnRfcGhvc3Bob19yZXN1bHRzJGRpZmZlcmVuY2UubG9uZy52cy5zaG9ydCA8IDApCgpudW1faW5jcmVhc2VkX3Bob3NwaG9yeWxhdGlvbl9zaXRlcyA8LSBzdW0oc2lnbmlmaWNhbnRfcHBfcmVzdWx0cyRkaWZmZXJlbmNlLmxvbmcudnMuc2hvcnQgPiAwKQpudW1fZGVjcmVhc2VkX3Bob3NwaG9yeWxhdGlvbl9zaXRlcyA8LSBzdW0oc2lnbmlmaWNhbnRfcHBfcmVzdWx0cyRkaWZmZXJlbmNlLmxvbmcudnMuc2hvcnQgPCAwKQoKbnVtX2luY3JlYXNlZF9wcm90ZWlucyA8LSBzdW0oc2lnbmlmaWNhbnRfcHFfcmVzdWx0cyRkaWZmZXJlbmNlLmxvbmcudnMuc2hvcnQgPiAwKQpudW1fZGVjcmVhc2VkX3Byb3RlaW5zIDwtIHN1bShzaWduaWZpY2FudF9wcV9yZXN1bHRzJGRpZmZlcmVuY2UubG9uZy52cy5zaG9ydCA8IDApCgpudW1faW5jcmVhc2VkX2tzZWEgPC0gc3VtKHNpZ25pZmljYW50X2tzZWFfcmVzdWx0cyRkaWZmZXJlbmNlLmxvbmcudnMuc2hvcnQgPiAwKQpudW1fZGVjcmVhc2VkX2tzZWEgPC0gc3VtKHNpZ25pZmljYW50X2tzZWFfcmVzdWx0cyRkaWZmZXJlbmNlLmxvbmcudnMuc2hvcnQgPCAwKQoKbnVtX2luY3JlYXNlZF9ybmEgPC0gc3VtKHNpZ25pZmljYW50X3JuYV9yZXN1bHRzJGRpZmZlcmVuY2UubG9uZy52cy5zaG9ydCA+IDApCm51bV9kZWNyZWFzZWRfcm5hIDwtIHN1bShzaWduaWZpY2FudF9ybmFfcmVzdWx0cyRkaWZmZXJlbmNlLmxvbmcudnMuc2hvcnQgPCAwKQoKYGBgCgoKTm93IGFkZCB0aGUgaW5jcmVhc2VkIGFuZCBkZWNyZWFzZWQgZnJvbSBlYWNoIGRhdGFzZXQgdG8gY3JlYXRlIGEgcGxvdCB0byBjb21wYXJlOiAKYGBge3J9CiMgaGF2ZSB0aGVtIGFsbCBhcyBhIGRhdGFmcmFtZSBmb3IgdGhlIHBsb3QKZGF0YV9hbGwgPC0gZGF0YS5mcmFtZSgKICBEYXRhc2V0ID0gcmVwKGMoIlBob3NwaG9wcm90ZWlucyIsICJwcC1pbmRleCIsICJQcm90ZWlucyIsICJLU0VBIiwgIlJOQSIpLCBlYWNoID0gMiksCiAgRXhwcmVzc2lvbiA9IHJlcChjKCJJbmNyZWFzZWQiLCAiRGVjcmVhc2VkIiksIDUpLAogIENvdW50ID0gYygKICAgIG51bV9pbmNyZWFzZWRfcGhvc3Bob3Byb3RlaW5zLCBudW1fZGVjcmVhc2VkX3Bob3NwaG9wcm90ZWlucywKICAgIG51bV9pbmNyZWFzZWRfcGhvc3Bob3J5bGF0aW9uX3NpdGVzLCBudW1fZGVjcmVhc2VkX3Bob3NwaG9yeWxhdGlvbl9zaXRlcywKICAgIG51bV9pbmNyZWFzZWRfcHJvdGVpbnMsIG51bV9kZWNyZWFzZWRfcHJvdGVpbnMsCiAgICBudW1faW5jcmVhc2VkX2tzZWEsIG51bV9kZWNyZWFzZWRfa3NlYSwKICAgIG51bV9pbmNyZWFzZWRfcm5hLCBudW1fZGVjcmVhc2VkX3JuYQogICkKKQoKYGBgCgpgYGB7cn0KCiNjcmVhdGUgdGhlIHBsb3QgCgpnZ3Bsb3QoZGF0YV9hbGwsIGFlcyh4ID0gRGF0YXNldCwgeSA9IENvdW50LCBmaWxsID0gRXhwcmVzc2lvbikpICsKICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IiwgcG9zaXRpb24gPSAiZG9kZ2UiKSArCiAgdGhlbWVfbWluaW1hbCgpICsKICBsYWJzKHRpdGxlID0gIk51bWJlciBvZiBpbmNyZWFzZWQgYW5kIGRlY3JlYXNlZCBzaWduaWZpY2FudCBmZWF0dXJlcyIsCiAgICAgICB4ID0gIkRhdGFzZXRzIiwKICAgICAgIHkgPSAiTnVtYmVyIG9mIEZlYXR1cmVzIikgKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoIkluY3JlYXNlZCIgPSAic2t5Ymx1ZSIsICJEZWNyZWFzZWQiID0gInNhbG1vbiIpKSArCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxKSkgKwogIGdlb21fdGV4dChhZXMobGFiZWwgPSBDb3VudCksIAogICAgICAgICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKHdpZHRoID0gMC45KSwgCiAgICAgICAgICAgIHZqdXN0ID0gLTAuNSwgCiAgICAgICAgICAgIHNpemUgPSAzLjUpICAjIEFkanVzdCB0aGUgc2l6ZSBhcyBuZWVkZWQKCmBgYAoKTm93LCBmaW5kIHRoZSBjb21tb24gdGFyZ2V0cyAoc2lnbmlmaWNhbnQgZGlmZmVyZW50aWFsbHkgZXhwcmVzc2VkIGZlYXR1cmVzKSBiZXR3ZWVuIGRhdGFzZXRzOgoKYGBge3J9CiNhbGwgc2lnbmlmaWNhbnQgcmVzdWx0cyAKcGhvc3BobyA8LSBzaWduaWZpY2FudF9waApwcEluZGV4IDwtIHNpZ25pZmljYW50X3BwCnByb3RlaW5xIDwtIHNpZ25pZmljYW50X3BxCktTRUEgPC0gaW5kaXZpZHVhbF9raW5hc2VzClJOQSA8LSBnZW5lX2xpc3Rfcm5hX2NsZWFuZWQKCmBgYAoKCmBgYHtyfQojIEZpbmQgY29tbW9uIGZlYXR1cmVzIGJldHdlZW4gZWFjaCAKI3Bob3NwaG8KY29tbW9uX3Bob3NwaG9fcHAgPC0gaW50ZXJzZWN0KHBob3NwaG8sIHBwSW5kZXgpCmNvbW1vbl9waG9zcGhvX3Byb3RlaW4gPC0gaW50ZXJzZWN0KHBob3NwaG8sIHByb3RlaW5xKQpjb21tb25fcGhvc3Bob19LU0VBIDwtIGludGVyc2VjdChwaG9zcGhvLCBLU0VBKQpjb21tb25fcGhvc3Bob19STkEgPC0gaW50ZXJzZWN0KHBob3NwaG8sIFJOQSkKI3BwLWluZGV4CmNvbW1vbl9wcF9wcm90ZWluIDwtIGludGVyc2VjdChwcEluZGV4LCBwcm90ZWlucSkKY29tbW9uX3BwX0tTRUEgPC0gaW50ZXJzZWN0KHBwSW5kZXgsIEtTRUEpCmNvbW1vbl9wcF9STkEgPC0gaW50ZXJzZWN0KHBwSW5kZXgsIFJOQSkKI3Byb3RlaW4gcXVhbnRpZmljYXRpb24KY29tbW9uX3Byb3RlaW5fS1NFQSA8LSBpbnRlcnNlY3QocHJvdGVpbnEsIEtTRUEpCmNvbW1vbl9wcm90ZWluX1JOQSA8LSBpbnRlcnNlY3QocHJvdGVpbnEsIFJOQSkKI2xhc3Qgb25lLSBSTkEKY29tbW9uX0tTRUFfUk5BIDwtIGludGVyc2VjdChLU0VBLCBSTkEpCgojVG8gc2VlIGlmIGFueSBlbGVtZW50IGlzIGNvbW1vbiBhY3Jvc3MgYWxsIGRhdGFzZXRzCmNvbW1vbl9hbGwgPC0gUmVkdWNlKGludGVyc2VjdCwgbGlzdChwaG9zcGhvLCBwcEluZGV4LCBwcm90ZWlucSwgS1NFQSwgUk5BKSkKCmBgYAoKYGBge3J9Cmluc3RhbGwucGFja2FnZXMoIlZlbm5EaWFncmFtIikKbGlicmFyeShWZW5uRGlhZ3JhbSkKYGBgCgoKYGBge3J9CiMgVmVubiBkaWFncmFtIGNyZWF0ZWQgdG8gYmV0dGVyIHZpZXcgdGhlIGNvbW1vbiByZXN1bHRzIC8gLSB1c2luZyB0aGUgc2lnbmlmaWNhbnRfcmVzdWx0cyAKdmVubi5wbG90IDwtIHZlbm4uZGlhZ3JhbSgKICB4ID0gbGlzdCgKICAgIFBob3NwaG9wcm90ZWlucyA9IHBob3NwaG8sCiAgICAicHAtaW5kZXgiID0gcHBJbmRleCwKICAgIFByb3RlaW5zID0gcHJvdGVpbnEsCiAgICBLU0VBID0gS1NFQSwKICAgIFJOQSA9IFJOQQogICksCiAgZmlsZW5hbWUgPSBOVUxMLCAgIyBTZXQgdG8gTlVMTCB0byBwbG90IGRpcmVjdGx5CiAgZmlsbCA9IGMoInJlZCIsICJibHVlIiwgImdyZWVuIiwgInllbGxvdyIsICJwdXJwbGUiKSwgI2NvbG9ycyB0byBiZXR0ZXIgdmlldyB0aGUgcmVzdWx0cyAKICBhbHBoYSA9IDAuNSwKICBjZXggPSAxLjUsCiAgY2F0LmNleCA9IDEuNSwKICBjYXQucG9zID0gMCwKICBjYXQuZGlzdCA9IDAuMDUsCiAgY2F0LmRlZmF1bHQucG9zID0gIm91dGVyIiwKICByb3RhdGlvbi5kZWdyZWUgPSAwLAogIG1hcmdpbiA9IDAuMSwKICBsd2QgPSAyLAogIGx0eSA9ICdzb2xpZCcsCiAgY29sID0gYygicmVkIiwgImJsdWUiLCAiZ3JlZW4iLCAieWVsbG93IiwgInB1cnBsZSIpLAogIHByaW50Lm1vZGUgPSBjKCJyYXciKSwKICBzaWdkaWdzID0gMgopCgojUGxvdCB0aGUgZGlhZ3JhbSAKZ3JpZC5uZXdwYWdlKCkKZ3JpZC5kcmF3KHZlbm4ucGxvdCkKCmBgYAoKCk5PVywgRFJVRyBTRU5TSVRJVklUWSBTQ09SRVMgVVNJTkcgVEhFIERSVUcgU0VOU0lUSVZJVFkgVEFCTEU6IAoKCmBgYHtyfQoKI2ZpbHRlciBmb3Igb25seSB0aGUgc2hvcnQgYW5kIGxvbmcgc3Vydml2YWwgZ3JvdXBzIApEUlVHX3Nob3J0X3NhbXBsZXMgPC0gaW50ZXJzZWN0KHNob3J0X3NhbXBsZXMsIGNvbG5hbWVzKFRhYmxlX29mX3NEU1MpKQpEUlVHX2xvbmdfc2FtcGxlcyA8LSBpbnRlcnNlY3QobG9uZ19zYW1wbGVzLCBjb2xuYW1lcyhUYWJsZV9vZl9zRFNTKSkKCnRhYmxlX29mX3NEU1NfZmlsdGVyZWRfc2hvcnQgPC0gVGFibGVfb2Zfc0RTUyAlPiUKICBkcGx5cjo6c2VsZWN0KGRydWcsIGZ1bmN0aW9uYWwuY2xhc3MsIG1lY2hhbmlzbS50YXJnZXQsIGRldmVsb3BtZW50LnBoYXNlLCBhbGxfb2YoRFJVR19zaG9ydF9zYW1wbGVzKSkKCnRhYmxlX29mX3NEU1NfZmlsdGVyZWRfbG9uZyA8LSBUYWJsZV9vZl9zRFNTICU+JQogIGRwbHlyOjpzZWxlY3QoZHJ1ZywgZnVuY3Rpb25hbC5jbGFzcywgbWVjaGFuaXNtLnRhcmdldCwgZGV2ZWxvcG1lbnQucGhhc2UsIGFsbF9vZihEUlVHX2xvbmdfc2FtcGxlcykpCgoKYGBgCgpGb3IgYWxsIG9mIHRoZXNlIHRha2UgaW50byBhY2NvdW50IHRoYXQgdGhlcmUgd2VyZSBtaXNzaW5nIHZhbHVlcyBpbiBzb21lLCBzbyBmdW5jdGlvbiBjcmVhdGVkIHRvIGhhdmUgZXZlcnl0aGluZyBudW1lcmljIGFuZCByZW1vdmUgc3VjaCB1bndhbnRlZCB2YWx1ZXMKCkZpcnN0LCBmb3IgQ0RLTjFCOiAKYGBge3J9CgojRm9yIENES04xQiAKCiMgRmlsdGVyIGZvciBkcnVncyB0YXJnZXRpbmcgJ0NESycgKGZvciBDREsgaW5oaWJpdG9ycykKc2hvcnRfQ0RLIDwtIHRhYmxlX29mX3NEU1NfZmlsdGVyZWRfc2hvcnQgJT4lIGZpbHRlcihncmVwbCgiQ0RLIiwgbWVjaGFuaXNtLnRhcmdldCwgaWdub3JlLmNhc2UgPSBUUlVFKSkKCmxvbmdfQ0RLIDwtIHRhYmxlX29mX3NEU1NfZmlsdGVyZWRfbG9uZyAlPiUgZmlsdGVyKGdyZXBsKCJDREsiLCBtZWNoYW5pc20udGFyZ2V0LCBpZ25vcmUuY2FzZSA9IFRSVUUpKQoKI0Z1bmN0aW9uIHVzZWQgdG8gY2xlYW4gYW5kIGNvbnZlcnQgY29sdW1ucyB0byBudW1lcmljCmNvbnZlcnRfY29sdW1uc190b19udW1lcmljIDwtIGZ1bmN0aW9uKGRmKSB7CiAgZGYgJT4lCiAgICBtdXRhdGUoYWNyb3NzKHN0YXJ0c193aXRoKCJUIiksIGZ1bmN0aW9uKHgpIHsKICAgICAgYXMubnVtZXJpYyhnc3ViKCJbXjAtOS5dIiwgIiIsIGFzLmNoYXJhY3Rlcih4KSkpICAjIFJlbW92ZSBub24tbnVtZXJpYyBjaGFyYWN0ZXJzIGJlZm9yZSBjb252ZXJzaW9uCiAgICB9LCAubmFtZXMgPSAibnVtZXJpY197Y29sfSIpKQp9CgojYXBwbHkgdGhlIGZ1bmN0aW9uIHRvIGVhY2ggZ3JvdXAKc2hvcnRfQ0RLIDwtIHNob3J0X0NESyAlPiUgY29udmVydF9jb2x1bW5zX3RvX251bWVyaWMoKQpsb25nX0NESyA8LSBsb25nX0NESyAlPiUgY29udmVydF9jb2x1bW5zX3RvX251bWVyaWMoKQoKIyBDYWxjdWxhdGUgbWVhbiBzZW5zaXRpdml0eSBzY29yZSBmb3IgZWFjaCBkcnVnIC0gZXhjbHVkaW5nIE5Bcy9taXNzaW5nIHZhbHVlcyAKc2hvcnRfQ0RLIDwtIHNob3J0X0NESyAlPiUKICByb3d3aXNlKCkgJT4lCiAgbXV0YXRlKG1lYW5fc2Vuc2l0aXZpdHkgPSBtZWFuKGNfYWNyb3NzKHN0YXJ0c193aXRoKCJudW1lcmljXyIpKSwgbmEucm0gPSBUUlVFKSkKCmxvbmdfQ0RLIDwtIGxvbmdfQ0RLICU+JQogIHJvd3dpc2UoKSAlPiUKICBtdXRhdGUobWVhbl9zZW5zaXRpdml0eSA9IG1lYW4oY19hY3Jvc3Moc3RhcnRzX3dpdGgoIm51bWVyaWNfIikpLCBuYS5ybSA9IFRSVUUpKQoKI3RoZW4gY2FsY3VsYXRlIG92ZXJhbGwgbWVhbnMKbWVhbl9zZW5zaXRpdml0eV9zaG9ydCA8LSBtZWFuKHNob3J0X0NESyRtZWFuX3NlbnNpdGl2aXR5LCBuYS5ybSA9IFRSVUUpCm1lYW5fc2Vuc2l0aXZpdHlfbG9uZyA8LSBtZWFuKGxvbmdfQ0RLJG1lYW5fc2Vuc2l0aXZpdHksIG5hLnJtID0gVFJVRSkKCiNQcmludCBvdmVyYWxsIG1lYW4gc2Vuc2l0aXZpdHkgc2NvcmUKcHJpbnQoIk1lYW4gU2Vuc2l0aXZpdHkgU2NvcmVzOiIpCnByaW50KHBhc3RlKCJTaG9ydCBTdXJ2aXZhbCBHcm91cDogIiwgbWVhbl9zZW5zaXRpdml0eV9zaG9ydCkpCnByaW50KHBhc3RlKCJMb25nIFN1cnZpdmFsIEdyb3VwOiAiLCBtZWFuX3NlbnNpdGl2aXR5X2xvbmcpKQoKYGBgCgoKRm9yIEFDU1MyOiAKCmBgYHtyfQoKI0ZPUiBBQ1NTMiAKCiNUaGUgZnVuY3Rpb24gdG8gY2xlYW4gYW5kIGNvbnZlcnQgY29sdW1ucyB0byBudW1lcmljCmNvbnZlcnRfY29sdW1uc190b19udW1lcmljIDwtIGZ1bmN0aW9uKGRmKSB7CiAgZGYgJT4lCiAgICBtdXRhdGUoYWNyb3NzKHN0YXJ0c193aXRoKCJUIiksIH5hcy5udW1lcmljKGFzLmNoYXJhY3RlciguKSkpKQp9CgojZmlsdGVyIGZvciB0aGUgZHJ1Z3MgaW50ZXJhY3Rpbmcgd2l0aCBBQ1NTMiBpZGVudGlmaWVkIGluIERHSWIKQUNTUzJfc2hvcnQgPC0gdGFibGVfb2Zfc0RTU19maWx0ZXJlZF9zaG9ydCAlPiUKICBmaWx0ZXIoZHJ1ZyAlaW4lIGMoIkRvY2V0YXhlbCIsICJHZW1jaXRhYmluZSIpKSAlPiUKICBjb252ZXJ0X2NvbHVtbnNfdG9fbnVtZXJpYygpCgpBQ1NTMl9sb25nIDwtIHRhYmxlX29mX3NEU1NfZmlsdGVyZWRfbG9uZyAlPiUKICBmaWx0ZXIoZHJ1ZyAlaW4lIGMoIkRvY2V0YXhlbCIsICJHZW1jaXRhYmluZSIpKSAlPiUKICBjb252ZXJ0X2NvbHVtbnNfdG9fbnVtZXJpYygpCgojIENhbGN1bGF0ZSBtZWFuIHNlbnNpdGl2aXR5IHNjb3JlIGZvciBlYWNoIGRydWcgLSBleGNsdWRpbmcgdGhlIE5BcwpBQ1NTMl9zaG9ydCA8LSBBQ1NTMl9zaG9ydCAlPiUKICByb3d3aXNlKCkgJT4lCiAgbXV0YXRlKG1lYW5fc2Vuc2l0aXZpdHkgPSBtZWFuKGNfYWNyb3NzKHN0YXJ0c193aXRoKCJUIikpLCBuYS5ybSA9IFRSVUUpKQoKQUNTUzJfbG9uZyA8LSBBQ1NTMl9sb25nICU+JQogIHJvd3dpc2UoKSAlPiUKICBtdXRhdGUobWVhbl9zZW5zaXRpdml0eSA9IG1lYW4oY19hY3Jvc3Moc3RhcnRzX3dpdGgoIlQiKSksIG5hLnJtID0gVFJVRSkpCgojIENhbGN1bGF0ZSBvdmVyYWxsIG1lYW5zCm1lYW5fQUNTUzJfc2hvcnQgPC0gbWVhbihBQ1NTMl9zaG9ydCRtZWFuX3NlbnNpdGl2aXR5LCBuYS5ybSA9IFRSVUUpCm1lYW5fQUNTUzJfbG9uZyA8LSBtZWFuKEFDU1MyX2xvbmckbWVhbl9zZW5zaXRpdml0eSwgbmEucm0gPSBUUlVFKQoKIyBQcmludCBvdmVyYWxsIG1lYW4gc2Vuc2l0aXZpdHkgc2NvcmVzCnByaW50KCJNZWFuIFNlbnNpdGl2aXR5IFNjb3JlczoiKQpwcmludChwYXN0ZSgiU2hvcnQgU3Vydml2YWwgR3JvdXA6ICIsIG1lYW5fQUNTUzJfc2hvcnQpKQpwcmludChwYXN0ZSgiTG9uZyBTdXJ2aXZhbCBHcm91cDogIiwgbWVhbl9BQ1NTMl9sb25nKSkKCmBgYAoKRm9yIENUTk5CMTogCgpgYGB7cn0KI0ZPUiBDVE5OQjEgCgojRmlsdGVyIGZvciB0aGUgZHJ1Z3MgaW50ZXJhY3Rpbmcgd2l0aCBDVE5OQjEgaWRlbnRpZmllZCBpbiBER0liCkNUTk5CMV9zaG9ydCA8LSB0YWJsZV9vZl9zRFNTX2ZpbHRlcmVkX3Nob3J0ICU+JQogIGZpbHRlcihkcnVnICVpbiUgYygiTGV0cm96b2xlIiwgIkltYXRpbmliIiwgIlRyaWNpcmliaW5lIiwgIlNvcmFmZW5pYiIsICJUZW1zaXJvbGltdXMiLCAiTGVuYWxpZG9taWRlIiwgIlRoYWxpZG9taWRlIiwgIkFaIDMxNDYiKSkgJT4lCiAgY29udmVydF9jb2x1bW5zX3RvX251bWVyaWMoKQoKQ1ROTkIxX2xvbmcgPC0gdGFibGVfb2Zfc0RTU19maWx0ZXJlZF9sb25nICU+JQogIGZpbHRlcihkcnVnICVpbiUgYygiTGV0cm96b2xlIiwgIkltYXRpbmliIiwgIlRyaWNpcmliaW5lIiwgIlNvcmFmZW5pYiIsICJUZW1zaXJvbGltdXMiLCAiTGVuYWxpZG9taWRlIiwgIlRoYWxpZG9taWRlIiwgIkFaIDMxNDYiKSkgJT4lCiAgY29udmVydF9jb2x1bW5zX3RvX251bWVyaWMoKQoKI0NhbGN1bGF0ZSBtZWFuIHNlbnNpdGl2aXR5IHNjb3JlIGZvciBlYWNoIGRydWcgLSBleGNsdWRpbmcgTkFzCkNUTk5CMV9zaG9ydCA8LSBDVE5OQjFfc2hvcnQgJT4lCiAgcm93d2lzZSgpICU+JQogIG11dGF0ZShtZWFuX3NlbnNpdGl2aXR5ID0gbWVhbihjX2Fjcm9zcyhzdGFydHNfd2l0aCgiVCIpKSwgbmEucm0gPSBUUlVFKSkKCkNUTk5CMV9sb25nIDwtIENUTk5CMV9sb25nICU+JQogIHJvd3dpc2UoKSAlPiUKICBtdXRhdGUobWVhbl9zZW5zaXRpdml0eSA9IG1lYW4oY19hY3Jvc3Moc3RhcnRzX3dpdGgoIlQiKSksIG5hLnJtID0gVFJVRSkpCgojQ2FsY3VsYXRlIG92ZXJhbGwgbWVhbnMKbWVhbl9DVE5OQjFfc2hvcnQgPC0gbWVhbihDVE5OQjFfc2hvcnQkbWVhbl9zZW5zaXRpdml0eSwgbmEucm0gPSBUUlVFKQptZWFuX0NUTk5CMV9sb25nIDwtIG1lYW4oQ1ROTkIxX2xvbmckbWVhbl9zZW5zaXRpdml0eSwgbmEucm0gPSBUUlVFKQoKIyBQcmludCAKcHJpbnQoIk1lYW4gU2Vuc2l0aXZpdHkgU2NvcmVzOiIpCnByaW50KHBhc3RlKCJTaG9ydCBTdXJ2aXZhbCBHcm91cDogIiwgbWVhbl9DVE5OQjFfc2hvcnQpKQpwcmludChwYXN0ZSgiTG9uZyBTdXJ2aXZhbCBHcm91cDogIiwgbWVhbl9DVE5OQjFfbG9uZykpCgpgYGAKCkZvciBNQVA0SzUgLSBNSU5LMToKCmBgYHtyfQojRk9SIE1BUDRLNS5NSU5LMS5lZGdlcyAKCiNGaWx0ZXIgZm9yIHRoZSBkcnVncyBpbnRlcmFjdGluZyB3aXRoIE1BUDRLNSBhbmQgTUlOSzEgaWRlbnRpZmllZCBpbiBER0liCk1NX3Nob3J0IDwtIHRhYmxlX29mX3NEU1NfZmlsdGVyZWRfc2hvcnQgJT4lCiAgZmlsdGVyKGRydWcgJWluJSBjKCJWYW5kZXRhbmliIiwgIkdlZml0aW5pYiIsICJEYXNhdGluaWIgYW5oeWRyb3VzIiwgIkNlZGlyYW5pYiIsICJEb3ZpdGluaWIiLCAiVG96YXNlcnRpYiIsICJMaW5pZmFuaWIiLCAiU29yYWZlbmliIiwgIkVybG90aW5pYiIsICJTTlMtMzE0IikpICU+JQogIGNvbnZlcnRfY29sdW1uc190b19udW1lcmljKCkKCk1NX2xvbmcgPC0gdGFibGVfb2Zfc0RTU19maWx0ZXJlZF9sb25nICU+JQogIGZpbHRlcihkcnVnICVpbiUgYygiVmFuZGV0YW5pYiIsICJHZWZpdGluaWIiLCAiRGFzYXRpbmliIGFuaHlkcm91cyIsICJDZWRpcmFuaWIiLCAiRG92aXRpbmliIiwgIlRvemFzZXJ0aWIiLCAiTGluaWZhbmliIiwgIlNvcmFmZW5pYiIsICJFcmxvdGluaWIiLCAiU05TLTMxNCIpKSAlPiUKICBjb252ZXJ0X2NvbHVtbnNfdG9fbnVtZXJpYygpCgoKI2NhbGN1bGF0ZSBtZWFuIHNlbnNpdGl2aXR5IHNjb3JlIGZvciBlYWNoIGRydWcgLSBleGNsdWRpbmcgTkFzCk1NX3Nob3J0IDwtIE1NX3Nob3J0ICU+JQogIHJvd3dpc2UoKSAlPiUKICBtdXRhdGUobWVhbl9zZW5zaXRpdml0eSA9IG1lYW4oY19hY3Jvc3Moc3RhcnRzX3dpdGgoIlQiKSksIG5hLnJtID0gVFJVRSkpCgpNTV9sb25nIDwtIE1NX2xvbmcgJT4lCiAgcm93d2lzZSgpICU+JQogIG11dGF0ZShtZWFuX3NlbnNpdGl2aXR5ID0gbWVhbihjX2Fjcm9zcyhzdGFydHNfd2l0aCgiVCIpKSwgbmEucm0gPSBUUlVFKSkKCiNDYWxjdWxhdGUgb3ZlcmFsbCBtZWFucwptZWFuX01NX3Nob3J0IDwtIG1lYW4oTU1fc2hvcnQkbWVhbl9zZW5zaXRpdml0eSwgbmEucm0gPSBUUlVFKQptZWFuX01NX2xvbmcgPC0gbWVhbihNTV9sb25nJG1lYW5fc2Vuc2l0aXZpdHksIG5hLnJtID0gVFJVRSkKCiNQcmludCByZXN1bHRzCnByaW50KCJNZWFuIFNlbnNpdGl2aXR5IFNjb3JlczoiKQpwcmludChwYXN0ZSgiU2hvcnQgU3Vydml2YWwgR3JvdXA6ICIsIG1lYW5fTU1fc2hvcnQpKQpwcmludChwYXN0ZSgiTG9uZyBTdXJ2aXZhbCBHcm91cDogIiwgbWVhbl9NTV9sb25nKSkKCmBgYApGb3IgUFJLRDE6IAoKCmBgYHtyfQojRk9SIFBSS0QxCgojRmlsdGVyIGZvciB0aGUgZHJ1Z3MgaW50ZXJhY3Rpbmcgd2l0aCBQUktEMSBpZGVudGlmaWVkIGluIERHSWIKUFJLRDFfc2hvcnQgPC0gdGFibGVfb2Zfc0RTU19maWx0ZXJlZF9zaG9ydCAlPiUKICBmaWx0ZXIoZHJ1ZyAlaW4lIGMoIk1pZG9zdGF1cmluIiwgIkJyeW9zdGF0aW4iKSkgJT4lCiAgY29udmVydF9jb2x1bW5zX3RvX251bWVyaWMoKQoKUFJLRDFfbG9uZyA8LSB0YWJsZV9vZl9zRFNTX2ZpbHRlcmVkX2xvbmcgJT4lCiAgZmlsdGVyKGRydWcgJWluJSBjKCJNaWRvc3RhdXJpbiIsICJCcnlvc3RhdGluIikpICU+JQogIGNvbnZlcnRfY29sdW1uc190b19udW1lcmljKCkKCgojQ2FsY3VsYXRlIG1lYW4gc2Vuc2l0aXZpdHkgc2NvcmUgZm9yIGVhY2ggZHJ1ZyAtIGV4Y2x1ZGluZyB0aGUgTkFzClBSS0QxX3Nob3J0IDwtIFBSS0QxX3Nob3J0ICU+JQogIHJvd3dpc2UoKSAlPiUKICBtdXRhdGUobWVhbl9zZW5zaXRpdml0eSA9IG1lYW4oY19hY3Jvc3Moc3RhcnRzX3dpdGgoIlQiKSksIG5hLnJtID0gVFJVRSkpCgpQUktEMV9sb25nIDwtIFBSS0QxX2xvbmcgJT4lCiAgcm93d2lzZSgpICU+JQogIG11dGF0ZShtZWFuX3NlbnNpdGl2aXR5ID0gbWVhbihjX2Fjcm9zcyhzdGFydHNfd2l0aCgiVCIpKSwgbmEucm0gPSBUUlVFKSkKCiNDYWxjdWxhdGUgb3ZlcmFsbCBtZWFucwptZWFuX1BSS0QxX3Nob3J0IDwtIG1lYW4oUFJLRDFfc2hvcnQkbWVhbl9zZW5zaXRpdml0eSwgbmEucm0gPSBUUlVFKQptZWFuX1BSS0QxX2xvbmcgPC0gbWVhbihQUktEMV9sb25nJG1lYW5fc2Vuc2l0aXZpdHksIG5hLnJtID0gVFJVRSkKCiNQcmludCBvdmVyYWxsIG1lYW5zCnByaW50KCJNZWFuIFNlbnNpdGl2aXR5IFNjb3JlczoiKQpwcmludChwYXN0ZSgiU2hvcnQgU3Vydml2YWwgR3JvdXA6ICIsIG1lYW5fUFJLRDFfc2hvcnQpKQpwcmludChwYXN0ZSgiTG9uZyBTdXJ2aXZhbCBHcm91cDogIiwgbWVhbl9QUktEMV9sb25nKSkKCmBgYAoKVG8gY3JlYXRlIGEgcGxvdCBmb3IgdGhlIFJlc3VsdHMgc2VjdGlvbiBzaG93aW5nIGFsbCB0aGUgbWVhbiBkcnVnIHNlbnNpdGl2aXR5IHNjb3JlIG9mIHRoZXNlIGRydWdzOgoKYGBge3J9CiNjcmVhdGUgZGF0YWZyYW1lIC0gYWRkIGFsbApkYXRhIDwtIGRhdGEuZnJhbWUoCiAgRmVhdHVyZSA9IGMoIkNES04xQiIsICJBQ1NTMiIsICJDVE5OQjEiLCAiTUFQNEs1L01JTksxIiwgIlBSS0QxIiksCiAgU2hvcnRfU3Vydml2YWxfR3JvdXAgPSBjKG1lYW5fc2Vuc2l0aXZpdHlfc2hvcnQsIG1lYW5fQUNTUzJfc2hvcnQsIG1lYW5fQ1ROTkIxX3Nob3J0LCBtZWFuX01NX3Nob3J0LCBtZWFuX1BSS0QxX3Nob3J0KSwKICBMb25nX1N1cnZpdmFsX0dyb3VwID0gYyhtZWFuX3NlbnNpdGl2aXR5X2xvbmcsIG1lYW5fQUNTUzJfbG9uZywgbWVhbl9DVE5OQjFfbG9uZywgbWVhbl9NTV9sb25nLCBtZWFuX1BSS0QxX2xvbmcpCikKCiNoYXZlIHRoZSBkYXRhIHRvIGxvbmcgZm9ybWF0IGZvciBnZ3Bsb3QyCmxpYnJhcnkocmVzaGFwZTIpCmRhdGFfbWVsdGVkIDwtIG1lbHQoZGF0YSwgaWQudmFycyA9ICJGZWF0dXJlIiwgdmFyaWFibGUubmFtZSA9ICJHcm91cCIsIHZhbHVlLm5hbWUgPSAiTWVhbl9TZW5zaXRpdml0eSIpCgpgYGAKCmBgYHtyfQojIFRoZSBwbG90IGZvciBkcnVnIHNlbnNpdGl2aXR5IAoKZ2dwbG90KGRhdGFfbWVsdGVkLCBhZXMoeCA9IEZlYXR1cmUsIHkgPSBNZWFuX1NlbnNpdGl2aXR5LCBmaWxsID0gR3JvdXApKSArCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIsIHBvc2l0aW9uID0gImRvZGdlIikgKwogIGdlb21fdGV4dChhZXMobGFiZWwgPSByb3VuZChNZWFuX1NlbnNpdGl2aXR5LCAyKSksIAogICAgICAgICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKHdpZHRoID0gMC45KSwgCiAgICAgICAgICAgIHZqdXN0ID0gLTAuMywgCiAgICAgICAgICAgIHNpemUgPSAzLjUpICsKICB0aGVtZV9taW5pbWFsKCkgKwogIGxhYnModGl0bGUgPSAiTWVhbiBEcnVnIFNlbnNpdGl2aXR5IFNjb3JlcyBieSBGZWF0dXJlIiwKICAgICAgIHggPSAiRmVhdHVyZSIsCiAgICAgICB5ID0gIk1lYW4gU2Vuc2l0aXZpdHkgU2NvcmUiLAogICAgICAgZmlsbCA9ICJHcm91cCIpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEpKQoKCmBgYAoK